这是我的代码
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
/**************************************************
a is a pointer to an array of strings
b is a string
This function appends b to *a
n is the number of strings currently "held" by *a
**************************************************/
int append(char ***a, char *b, unsigned long n) {
if (a && *a && **a) {
char** tmp = realloc(*a, (n + 1) * sizeof(**a));
if (tmp) {
tmp[n] = b;
*a = tmp;
return 0;
}
}
return -1;
}
void test() {
char *words[7] = { "food", "is", "good", "to", "eat,", "like", "pizza" };
char** a = malloc(1 * sizeof(*a));
for (int i = 0; i < 7; i++) {
append(&a, words[i], i);
int j = 0;
while (j <= i)
printf("%s ", a[j++]);
printf("\n");
}
}
int main() {
test();
return 0;
}
代码始终可以正常编译且没有警告。可执行文件按预期的方式运行的时间约为95%。但是大约有5%的时间,我遇到了细分错误。我知道故障发生在a[j++]
,但我不明白为什么。
答案 0 :(得分:4)
看看这一行:
if (a && *a && **a)
当malloc
最初由a
指向一个元素的空间时,您实际上从未初始化过该内存。结果,**a
未初始化,因此读取它被视为未定义行为。实际上,我怀疑有时分配给您的内存在某些情况下是空指针,而在其他情况下则不是,这说明了脆弱性。
我实际上认为您甚至不需要检查*a
和**a
。只要指针a
本身不是空指针,就可以修改其指向的指针(*a
)。此外,这里实际上不需要知道由*a
指向的数组的第一个元素是否为null(**a
)。因此,您只需将此支票替换为
if (a)
我会走得更远,甚至不为a
分配初始数组,因为您实际上不会读取存储在其中的值。
其他要做的事情:函数append
返回一个状态代码,该状态代码通知操作是成功还是失败。最好在每次调用append
时检查该值,以防万一失败。您可能还希望将外部if
更改为assert
,以便如果有人用错误的参数调用它,则它会暂停并报告违反先决条件的问题,而不是失败并显示错误代码。毕竟,如果问题是“您给了我不可能正确的论点”,则意味着代码中存在逻辑错误。
希望这会有所帮助!