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