fscanf()代码并不总是使内存崩溃,但有时

fscanf()代码并不总是使内存崩溃,但有时,c,pointers,malloc,scanf,coredump,C,Pointers,Malloc,Scanf,Coredump,========================= 代码(文件名为test.c) ======== 问题: 当我在下面执行了好几次 test 1 test 2 ... ... test 7 test 8 它经常粉碎类似于“核心转储”的东西,但正如我预期的那样工作 然而,当我输入高于9时,它永远不会崩溃 test 9 test 10 ... 是什么让这段代码崩溃的 fscanf正在尝试将数据写入您尚未分配的*arr[i]。您只分配了arr[i](您也没有初始化)。\include #包括 #

=========================

代码(文件名为test.c) ========

问题: 当我在下面执行了好几次

test 1
test 2
...
...
test 7
test 8
它经常粉碎类似于“核心转储”的东西,但正如我预期的那样工作

然而,当我输入高于9时,它永远不会崩溃

test 9
test 10
...


是什么让这段代码崩溃的

fscanf
正在尝试将数据写入您尚未分配的
*arr[i]
。您只分配了
arr[i]
(您也没有初始化)。

\include
#包括
#包括
int main(int argc,const char*argv[]
{
int i=0,num=atoi(argv[1]);
char**arr=(char**)malloc(num*sizeof(char*);
对于(int j=0;j

对于
fscanf(fp,“%s”,arr[i]),您需要为每个
arr[i]

分配alloc内存。问题是,您只为指针分配了空间,而没有为字符串本身分配空间。如果您正在为兼容POSIX.1-2008的平台或使用足够新的glibc(例如最近的Linux,可能也是MinGW)编程,这里有一个替代其他答案的方法:

您可以使用
a
说明符进行
%s
转换(详细信息请参阅),这会导致
scanf
为字符串分配内存(调用者负责调用
free()
on),因此对于您的代码:

// No need to cast return value of malloc or calloc.
// Optional: switched to calloc, which has overhead of zeroing memory,
// but also makes immediate segfault more likely on some bugs.
char **arr = calloc(num, sizeof(char*));
//...
for(i=0; i < num; i++) {
    int status = fscanf(fp,"%ms", arr[i] );
    assert(status==1); // really simple error checking added
}
//不需要强制转换malloc或calloc的返回值。
//可选:切换到calloc,这会增加内存归零的开销,
//但也会使某些bug更容易出现即时故障。
char**arr=calloc(num,sizeof(char*));
//...
对于(i=0;i
如前所述,完成后,您应该释放分配的内存:

for(i=0; i < num; i++) {
    free(arr[i]);
}
free(arr);
for(i=0;i

好处是,您不需要担心缓冲区溢出(如果文件大于可用虚拟内存,那么您将遇到麻烦,除非您为
说明符添加限制,请阅读手册页以了解详细信息…),并且您不会因为为较短的字符串分配过多空间而浪费任何内存。缺点是,
a
说明符不是由C标准定义的,因此它会降低代码到GNU和POSIX平台的可移植性,并可能导致老师拒绝它(如果是课程作业),以防万一。

是的,它是一个非斜体指针数组。那些字符串可以写在记忆中的任何地方。我很难理解。你能告诉我怎么做吗?请~!仅供参考:如果你的代码真的破坏了某些东西,你会有更多的担心。你想要的词是crash;)我很抱歉关于Surm,我是指崩溃,“AlxPakjw,那为什么你没有修复它?在C.没有<代码>新< /Cord>,甚至是C++,你不想<代码> For()代码>使用<代码>新< /COD>分配的,但是使用<代码> Debug < /C>。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc, const char * argv[])
{
    int i = 0, num = atoi(argv[1]);
    char** arr = (char**)malloc(num * sizeof(char*));
    for (int j = 0; j < num; j++) {
        arr[j] = (char*)malloc(100 * sizeof(char));
    }
    FILE* fp = fopen("test.txt", "r");
    if (arr == NULL) {
        printf("out of memory\n");
        exit(1);
    }
    if (fp == NULL) {
        printf("cannot open the file\n");
        exit(1);
    }

    for (; i < num; i++) {
        fscanf(fp, "%s", arr[i]);
        printf("%s\n", arr[i]);
    }
    for (int k = 0; k < num; k++) {
        free(arr[i]);
    }
    free(arr);
    return 0;
}
// No need to cast return value of malloc or calloc.
// Optional: switched to calloc, which has overhead of zeroing memory,
// but also makes immediate segfault more likely on some bugs.
char **arr = calloc(num, sizeof(char*));
//...
for(i=0; i < num; i++) {
    int status = fscanf(fp,"%ms", arr[i] );
    assert(status==1); // really simple error checking added
}
for(i=0; i < num; i++) {
    free(arr[i]);
}
free(arr);