无法在以null结尾的字符串上运行printf()

时间:2017-04-15 01:35:06

标签: c gdb

当我因某种原因传递以null结尾的字符串时,

printf()会抛出分段错误。

这是GDB中我的问题的演示


     λ sudo gdb -q notesearch
    Reading symbols from notesearch...done.
    (gdb) break 53
    Breakpoint 1 at 0x400b32: file notesearch.c, line 53.
    (gdb) run
    Starting program: /home/frosty/hack/chapter_2/code/notesearch 
    [DEBUG] UserID: 0
    [DEBUG] File Descriptor: 3

    Breakpoint 1, print_notes (fd=3, uid=0, searchstring=0x7fff3daf7fc0 "")
        at notesearch.c:53
    53          printf("%s\n", note_buffer);
    (gdb) x/8xb note_buffer
    0x7feb5a997168: 0x68    0x65    0x6c    0x6c    0x6f    0x0a    0x00    0x00
    (gdb) x/s note_buffer
    0x7feb5a997168: "hello\n"
    (gdb) next

    Program received signal SIGSEGV, Segmentation fault.
    _dl_fixup (l=, reloc_arg=)
        at ../elf/dl-runtime.c:148
    148 ../elf/dl-runtime.c: No such file or directory.
    (gdb) 

这是问题的源代码


    int print_notes(int fd, int uid, char *searchstring){
        int note_length = find_user_note(fd, uid);

        if (note_length == -1) 
            return 0; // End of file

        char* note_buffer;
        read(fd, note_buffer, note_length);

        note_buffer[note_length] = 0; // null terminator byte

        if(search_note(note_buffer, searchstring)) {
            printf("%s\n", note_buffer);
        }
        return 1;
    }

2 个答案:

答案 0 :(得分:0)

空终止符由\0而非0

表示

note_buffer[note_length] = 0;

应该是

note_buffer[note_length] = '\0';

答案 1 :(得分:0)

请记住,在C中,数组的索引是从0到(array-1的长度)

这一行:

char* note_buffer;

声明一个指向字符的初始化指针。 I.E.它的值取决于该位置当前存储器中的垃圾。这样的操作如访问垃圾“点”的位置将是未定义的行为并且可能导致seg故障事件。

强烈建议,在这一行之后:

char* note_buffer;

插入以下内容:(包括检查malloc()失败:

note_buffer = malloc( note_length+1 );
if( !note_buffer )
{
    perror( "malloc failed" ); 
    exit( EXIT_FAILURE );
}

// implied else, malloc successful

注意:如果+1调用malloc()以下行,则无法使用note_buffer[note_length] = 0;

0

将设置一个超出分配区域结尾的字节。这将是未定义的行为,并可能导致seg故障事件

此外,note_buffer[note_length] = '\0'; 的位模式为0x000000000000000000000000,而'\ 0'的位模式为0x00000000。隐式转换功能将在此实例中保存您,但不依赖于该功能,而是正确编码文字。所以该行应该是:

perror()

注意:stderr输出所附文本字符串以及操作系统认为错误发生的原因{{1}},这是应输出所有错误消息的地方。