layout: post title: 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