【问题标题】:Program crashing on a function prototype declaration程序在函数原型声明上崩溃
【发布时间】:2013-09-17 16:31:03
【问题描述】:

我尝试练习编写这个函数的通用函数:

void *scramble(void *arr, int ElemSize, int n, int *indArr); 但是每当我使用调试器运行程序时,它会在原型线上崩溃,使用 F11(Step Into)我会看到以下内容:

1.

#else  /* WPRFLAG */
            __initenv = envp;
            mainret = main(argc, argv, envp);
#endif  /* WPRFLAG */

2.

if ( !managedapp )
    exit(mainret);

然后控制台消息说:The program '[8108] 1.exe: Native' has exited with code 0 (0x0).

这是我的程序(请忽略逻辑编码错误,因为我想自己解决):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char BYTE;

void *scramble(void *arr, int ElemSize, int n, int *indArr);

void main()
{
    int indArr[5]={5,4,3,2,1};
    int numbers[5]={1,2,3,4,5};
    char letters[5]={'a','b','c','d','e'};

    int *newNum;
    char *newLet;

    newNum = (int*)scramble(numbers, sizeof(int), 5, indArr);
    newLet = (char*)scramble(letters, sizeof(char), 5, indArr);
}

void *scramble(void *arr, int ElemSize, int n, int *indArr)
{
    int i;
    BYTE *read, *write;
    void *res;

    res = malloc(ElemSize*n);

    write = (BYTE*)res;
    read = (BYTE*)arr;

    for (i = 0; i < n; i++)
    {
        memcpy(write + indArr[i]*ElemSize, read, ElemSize);
        read += ElemSize;
    }

    return res;
}

【问题讨论】:

  • 发布调用scramble 的代码会有所帮助。
  • @chux,我已经编辑并添加了整个代码
  • 您第一次致电memcpy(write + indArr[i]*ElemSize, read, ElemSize)memcpy(write + 5*ElemSize, read, ElemSize);。这似乎在write 之外。我想你想要int indArr[5]={4,3,2,1,0}。 (基于零的索引)
  • 你用的是什么调试器?通常,当程序以返回码 0 结束时,它已成功完成。
  • @chux,没错,我已经修复了这个问题,但程序仍然无法在调试器下运行。 \

标签: c crash memcpy function-prototypes


【解决方案1】:

如果您查看memcpy 行:

memcpy(write + indArr[i]*ElemSize, read, ElemSize);

如果inAddr[0] = 5indArr[0] 的目的地不正确。将内存想象成一个连续的块,指针write 指向开头。将 5 * ElemSize 添加到 write 会将其置于分配的内存范围之外。

 _______________________
|    |    |    |   |    | 1
 -----------------------
^- write                 ^- write + 5 * ElemSize

【讨论】:

  • 正如我在 cmets 中提到的,这是一个逻辑错误,并且已经修复。即使在修复它之后,程序也拒绝在 Visual Studio 的调试器下运行。
  • 调试器甚至不应该指向该行。尝试在第一次调用 scramble 时设置新断点。
  • @Freddie 看起来我们被匿名投票者击中了。
  • @chux 确实。您首先指出程序会在哪里出现段错误(如果调试器实际运行!),所以我赞成您的回答。
【解决方案2】:

OP 使用的是基于 1 的索引,而不是基于 0 的索引。这导致第一个 memcpy 写入边界外。修改代码如下。

// int indArr[5]={5,4,3,2,1};
int indArr[5]={4,3,2,1,0};

[编辑]

与@Freddie & 我的进一步研究未能复制 OP 的问题。 OP 发布的“崩溃”之后的 2 个步骤是正常退出之前的正常步骤。要么陈述的事情有问题,要么 OP 的调试器/编译器只是“知道”它不需要打扰那些讨厌的 scramble() 函数调用,并且可以早点回家去比尔的家。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-07
    • 2012-07-27
    • 1970-01-01
    • 2012-07-15
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多