仓库源文站点原文


layout: post title: C 結構成員使用的小陷阱

categories: ['C/C++']

在struct中對於char array使用sprintf或fgets函式直接賦值,操作上更加方便

但在函式中會自動補上'\n''\0',可能導致預期之外的行為。

Example code如下

#include <stdio.h>

typedef struct {
    char Name[10];
    char Phone[10];
    int Age;
} Info;

void DumpInfo(Info *info)
{
    printf("Name = %10.10s | Phone = %10.10s | Age = %d\n", 
        info->Name, info->Phone, info->Age);
}

int main(void) {
    Info info = { .Name = "AbCdEfGhIj", .Phone = "2369-9555", .Age = 19 };
    Info info2 = info;
    DumpInfo(&info);

    sprintf( info.Name, "%s", "AAAAAKKKKK" );
    DumpInfo(&info);

    snprintf( info2.Name, 10, "%s", "AAAAAGGGGG" );
    DumpInfo(&info2);

    char buff[32] = {};
    snprintf( buff, 32, "%s", "AAAAAGGGGG" );
    memcpy( info2.Name, buff, 10 );
    DumpInfo(&info2);
    return 0;
}

gcc的輸出結果

gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)

Name = AbCdEfGhIj | Phone =  2369-9555 | Age = 19
Name = AAAAAKKKKK | Phone =            | Age = 19
Name =  AAAAAGGGG | Phone =  2369-9555 | Age = 19
Name = AAAAAGGGGG | Phone =  2369-9555 | Age = 19

第一組因為補'\0'而存取超過範圍,影響了後面的member 第二組會截斷超過長度的字,而使得紀錄的資料少了一個Byte 必須先用一段緩衝區儲存資料,再用memcpy複製進對應的member中

llvm則是直接觸發chk_stack_fail而被abort掉了

Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-apple-darwin16.6.0

Segmentation fault