繁体   English   中英

如何克服访问数组指针时的段错误

[英]How to overcome Segfault on accessing pointer to array

访问指针时出现段错误

我正在开发简单的 GTK3 C 应用程序(使用 WSL2 和 VSCode),但是当我尝试从文件中反序列化结构时,我遇到了段错误(我对 gdb 不是很熟悉,所以当我尝试调试时我真的不能找到导致错误的行)。

我的代码

结构定义

typedef struct whatev {
    size_t id;
    char* name;
    int amount;
    float value;
    signed char state;
} SomeStruct;

Struct 是单独定义的,包括 header,在编译过程中不会引起任何问题(只是为了澄清)

Function 导致段错误

SomeStruct* checkLine(char* str) {
    char* readString;
    int d1;
    float f1;
    
    sscanf(str, "%100[^;];%d;%f", readString, &d1, &f1);
    // printf("Checking line: Read name: \"%s\", amount=%d, value=%f\n", readString, d1, f1);
    if (readString[0] != '\0') {
        SomeStruct* newLine = malloc(sizeof(SomeStruct));
        // strcpy(newLine->name, readString);
        newLine->name = readString;
        newLine->amount = d1;
        newLine->value = f1;
        return newLine;
    }
    return NULL;
}
SomeStruct* createStructsFromFile(FILE* filestream, size_t fileLength) {
    printf("Create struct from file: start\n");
    SomeStruct* js = malloc(fileLength * sizeof(js));
    SomeStruct* currentItem = malloc(sizeof(js));
    size_t failed = 0;
    size_t j = 0;
    unsigned int buffer_size = 500;
    
    // ERROR: Segfault somewhere here

    for (size_t i = 0; i < fileLength; i++) {
        char buffer[buffer_size];
        fgets(buffer, buffer_size, filestream);
        if ((currentItem = checkLine(buffer)) != NULL) {
            currentItem->id = j;
            currentItem->state = 0;

            js[j] = *currentItem;
            currentItem = (SomeStruct*)malloc(sizeof(js));
            j++;
        }
        else
            failed++;  // TODO
    }
    printf("Create struct from file: Finished creating, failed reading %zd / %zd lines\n", failed, fileLength);
    return js;
}

我的调试尝试

Breakpoint 5 at 0x80031a6: file FileOperations/fileOperations.c, line 125.
(gdb) step
[LWP 22523 exited]
createStructsFromFile: before assignment currentItem[0] (KsiążkaZPolskimiZnakami) to js[0]
123                 js[j] = *currentItem;
(gdb) display js
13: js = (SomeStruct *) 0x85663e0
(gdb) display js[0]
14: js[0] = {id = 139820112, name = 0x0, amount = 137883733, value = 2.80259693e-44, state = 0 '\000'}
(gdb) display js[1]
15: js[1] = {id = 90194313216, name = 0xfffffff <error: Cannot access memory at address 0xfffffff>, 
  amount = 0, value = 0, state = 21 '\025'}
(gdb) display js[19]
16: js[19] = {id = 67174657, name = 0x0, amount = 0, value = -8.99305959e+35, state = 54 '6'}
(gdb) display currentItem
17: currentItem = (SomeStruct *) 0x83f34b0
(gdb) display currentItem->name
18: currentItem->name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami"
(gdb) step

Thread 1 "main" hit Breakpoint 5, createStructsFromFile (filestream=0x696b736c6f505a61, 
    fileLength=7763297035996459851) at FileOperations/fileOperations.c:125
125                 printf("createStructsFromFile: inserted %zdth struct\n\n", j);
13: js = (SomeStruct *) 0x85663e0
14: js[0] = {id = 0, name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami", amount = 12, 
  value = 3.99000001, state = 0 '\000'}
15: js[1] = {id = 90194313216, name = 0xfffffff <error: Cannot access memory at address 0xfffffff>, 
  amount = 0, value = 0, state = 21 '\025'}
16: js[19] = {id = 67174657, name = 0x0, amount = 0, value = -8.99305959e+35, state = 54 '6'}
17: currentItem = (SomeStruct *) 0x83f34b0
18: currentItem->name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami"
(gdb) step
createStructsFromFile: inserted 0th struct

126                 currentItem = malloc(sizeof(js));
13: js = (SomeStruct *) 0x85663e0
14: js[0] = {id = 0, name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami", amount = 12, 
  value = 3.99000001, state = 0 '\000'}
15: js[1] = {id = 90194313216, name = 0xfffffff <error: Cannot access memory at address 0xfffffff>, 
  amount = 0, value = 0, state = 21 '\025'}
16: js[19] = {id = 67174657, name = 0x0, amount = 0, value = -8.99305959e+35, state = 54 '6'}
17: currentItem = (SomeStruct *) 0x83f34b0
18: currentItem->name = 0x7ffffffecf30 "KsiążkaZPolskimiZnakami"
(gdb) step
start pętli 1

Thread 1 "main" received signal SIGSEGV, Segmentation fault.
0x00007ffffeae2657 in ?? ()

示例数据库

KsiążkaZPolskimiZnakami;12;3.99
Book with a lot of spaces;44;2.99
OutOfStock;0;1.00
LiterallyFreeNotebook;99;0.00
NextLineTriesToMakeScanfError;1;255.12
;;
HopeThatReadingWillWork;12;66.72
ThisBookHas7Parts;3;12.50
لكن لا بد أن أوضح لك أن كل هذه الأفكار;6;12.5
ArabicAndNeat;8;11
NegativeQuantity;-12;5.00
NegativeValue;7;-2.22
!LL3G4L_$|gNS;10;7.5
 
AboveWasJustSpace;2;0.1
TooManyArguments;1;15.55;12
UnexpectedType;3232.1;55
71830;80085;AndOtherFunnyThings
\0;\0;\0
EscapeSequence\n\"exit(1);11;255.1
YesILoveDebugging,Why?;-0;-99999999999999.9999

期望

我想使用createStructsFromFile的 output 填充 GTK TreeView。我也尝试使用双指针,但为了调试,我简化了返回( size_t createStructsFromFile(FILE* filestream, size_t fileLength, JakasStruktura** js)

哪里出了问题,我该如何改进?

如果需要,可以在我的 GitHub上找到代码

(提交)[https://github.com/ikarmus2001/ProjektC/commit/761a1f2000ee8ab1c32efd8449c1b95f8f11a2c1]

提前致谢

代码将未初始化的 object readString传递给sscanf() ,导致未定义的行为(UB)。 @约翰尼莫普

char* readString;
...
sscanf(str, "%100[^;];%d;%f", readString, &d1, &f1);  // bad

反而

char readString[100+1];

检查返回值

测试扫描是否成功**

// sscanf(str, "%100[^;];%d;%f", readString, &d1, &f1);
if (sscanf(str, "%100[^;];%d;%f", readString, &d1, &f1) != 3) {
  Handle_bad_input();
}

需要字符串的副本

与其应对一个点,不如分配数据。

// newLine->name = readString;
newLine->name = malloc(strlen(readString) + 1);
if (newLine->name == NULL) {
  TBD_eror_handling();
}
strcpy(newLine->name, readString);

较早的SomeStruct* newLine = malloc(sizeof(SomeStruct)); 为结构分配了 memory,包括指针: .name成员。 然而指针仍然没有指向任何分配的字符串。

稍后的代码需要在完成结构后释放此分配。

mallocking 结构是否已经为该指针保留了 memory? SomeStruct* newLine = malloc(sizeof(SomeStruct)); newLine->name = readString;

没有为结构本身分配空间。 所以你得到其中之一

typedef struct whatev {
    size_t id;
    char* name;
    int amount;
    float value;
    signed char state;
} SomeStruct;

但是name没有指向任何地方(malloc 甚至不知道那里有一个指针,它只是为您提供整个结构的原始 memory)。 您现在也需要在某处name

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM