【发布时间】:2016-05-18 19:22:28
【问题描述】:
问题:
我很确定我的问题是对指针发生的事情的典型误解。我将在下面发布内存中发生的情况,因为我在这里的主要目标是学习如何正确调试,所以这可能是一篇关于其他微不足道的问题的长篇文章。
这是代码,首先:
/*Generate array with 500 to 1000 elements*/
/*In the calling function, I create something like 'int* x;' and pass '&x'*/
void gen_array(int** arr){
int size = rand() % (1001 - 500) + 500;
int i;
*arr = (int*) malloc(size*sizeof(int));
if (*arr == NULL){
printf("Allocation failed\n");
exit(1); //I know this is probably bad form
}
//Fill with some random numbers from 1 to 1000
for (i = 0; i < size; ++i)
*arr[i] = rand() % 1001;
}
它在for 循环的第一次迭代后中断(即i==1 时)。我不确定我分配错误malloc,还是在循环中分配错误。
这样调用:
int* x = NULL; //Tried without '= NULL' as well
gen_array(&x);
具体错误:
Unhandled exception at 0x00265E55 in test.exe: 0xC0000005: Access violation writing location 0xCCCCCCCC.
这是在first-chance exception 之后在完全相同的位置,但它们是在同一行代码中生成的(并且在执行期间的同一迭代中)。
我的分析尝试:
如果有帮助,这是一次尝试调试的(相关)分步说明(我正在 Visual Studio 中编译)。我想知道如何使用这些信息来帮助我将来进行调试。
- 在调用函数的开头,
x = 0xcccccccc(0xcccccccc=-842150451似乎是编译器用来填充未初始化值的东西)。设置为NULL后当然等于0x00000000。 - 调用
gen_array(int** arr),因为我将一个指针传递给一个指针,本地“双指针”是一个指向NULL 指针的地址:arr=0x0018facc {0x00000000 {???}}。 (这显示了所指向的值,因为 NULL 指针没有指向任何东西,所以有???) - 调用
malloc:现在arr=0x0018facc {0x00e97048 {-842150451}},所以*arr指向一个未初始化的值 - 第一次迭代(
i==0),生成的数字是588,所以现在arr=0x0018facc {0x00e97048 {588}}(也就是*arr指向的值是588)
i 增加到 1 后的下一次迭代崩溃。由于这是访问冲突,我通常会猜测 arr+1 不希望被写入。但是违规位置在0xCCCCCCCC,这个编译器用于未初始化数据的值。这是因为arr+1 在技术上未初始化吗?
编辑: 正如@GrzegorzSzpetkowski 建议的那样,我尝试将*arr[i] 更改为(*arr)[i]。它停止破裂!但是,没有新的随机值被创建/放置到数组中(这就是我担心根本没有创建数组的原因)。
编辑 2: 根据 @EOF 的建议,我更改了函数以返回大小,以便可以使用 int length = gen_array(&x); 之类的内容调用
我知道我也可以尝试从函数返回int*,但我想知道在从要初始化的调用函数传递指针的情况下这里具体发生了什么。
【问题讨论】:
-
在 Visual Studio 中,由于它编译为 C++,所以当我不强制转换时出现错误(构建失败):
error C2440: '=' : cannot convert from 'void *' to 'int *' -
你是否加入了
stdlib? -
*arr[i]->(*arr)[i]因为后缀具有更高的优先级。前一个 lhs 在您的上下文中没有意义。 -
无论如何,你的函数都是废话。如果您创建的分配大小是随机的,并且您没有任何方式通知调用者,则一旦函数返回,分配无法被安全访问。