在下面的代码中,代码在第四次执行 while 循环后崩溃,并在 strcpy 中崩溃
strcpy(userver_info[location].Tag_Name, field);
调试时,它给出了以下错误
Can't find a source file at "strcpy-sse2-unaligned.S"
我无法弄清楚导致这里崩溃的问题是什么,在遇到上述问题后,我做了结构填充,认为这可能是问题所在,即使这也没有解决,任何人都可以告诉我为什么代码崩溃。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFFER_SIZE 1024 #define NUM_OF_UNDERLYING_SERVER 0 #define SHM_ADDR_LEN 15 #define SERVER_NAME_LEN 25 #define TAG_NAME_LEN 25 #define TAG_DESC_LEN 30 #define ACCESS_LEVEL_LEN 5 #define DATA_TYPE_NAME_LEN 10 typedef struct { char SHM_Location[SHM_ADDR_LEN]; char Server_ID[SERVER_NAME_LEN]; char Tag_Name[TAG_NAME_LEN]; int Tag_ID; char Tag_Description[TAG_DESC_LEN]; char Access_Level[ACCESS_LEVEL_LEN]; char Data_Type[DATA_TYPE_NAME_LEN]; }u_server_info; typedef struct { int num_of_tags; u_server_info *underlying_server_data; }opcua_u_server; void parse_underlying_opcua_server(char * buffer, u_server_info *userver_info) { static int location = 0; char *field; /* get SHM_Location */ field = strtok(buffer,","); strcpy(userver_info[location].SHM_Location, field); /* get Server_ID */ field=strtok(NULL,","); strcpy(userver_info[location].Server_ID, field); /* get Tag_Name */ field = strtok(NULL,","); strcpy(userver_info[location].Tag_Name, field); /* get Tag_ID */ field=strtok(NULL,","); userver_info[location].Tag_ID = atoi(field); /* get Tag_Description */ field = strtok(NULL,","); strcpy(userver_info[location].Tag_Description, field); /* get Access_Level */ field = strtok(NULL,","); strcpy(userver_info[location].Access_Level, field); /* get Data_Type */ field = strtok(NULL,","); strcpy(userver_info[location].Data_Type, field); /* display the result */ printf("%st %st %st %dt %st %st %sn", userver_info[location].SHM_Location, userver_info[location].Server_ID, userver_info[location].Tag_Name, userver_info[location].Tag_ID, userver_info[location].Tag_Description, userver_info[location].Access_Level, userver_info[location].Data_Type); location++; } int get_line_count(char *filename) { FILE *fp; int line_count = 0; char c; fp = fopen(filename, "r"); if (fp == NULL){ printf("Unable to open file '%s' to count linesn",filename); return -1; } for (c = getc(fp); c != EOF; c = getc(fp)) if (c == 'n') // Increment count if this character is newline line_count = line_count + 1; fclose(fp); return line_count; } int main(int argc, char **argv) { char filename[] = "underlying_server.csv"; char buffer[BUFFER_SIZE]; FILE *fp; int tags_count = 0; opcua_u_server *ua_server = NULL; /* open the CSV file */ fp = fopen(filename,"r"); if( fp == NULL) { printf("Unable to open file '%s'n",filename); exit(EXIT_FAILURE); } tags_count = get_line_count(filename); /* Allocate memmory for each Underlying server */ ua_server= malloc(sizeof(opcua_u_server)); if (ua_server == NULL) { printf("Malloc failed"); exit(EXIT_FAILURE); } /* Allocate memory for each underlying server tag information */ ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data = malloc(tags_count * sizeof(ua_server->underlying_server_data)); if (ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data == NULL) { printf("Malloc failed"); exit(EXIT_FAILURE); } /* process the data */ while(fgets(buffer,BUFFER_SIZE,fp)) { parse_underlying_opcua_server(buffer, ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data); } ua_server->num_of_tags = tags_count; /*Reset the value for next server*/ tags_count = 0; /* close file */ fclose(fp); return(0); }
我的underlying_server.csv是这样的
1000,Server_1,Tag_1,3000,Created_tag_3000,AR,BOOL 1001,Server_1,Tag_2,3001,Created_tag_3001,AR,BOOL 1002,Server_1,Tag_3,3002,Created_tag_3002,AR,BOOL 1003,Server_1,Tag_4,3003,Created_tag_3003,AR,BOOL 1004,Server_1,Tag_5,3004,Created_tag_3004,AR,REAL 1005,Server_1,Tag_6,3005,Created_tag_3005,AR,REAL 1006,Server_1,Tag_7,3006,Created_tag_3006,AW,REAL 1007,Server_1,Tag_8,3007,Created_tag_3007,AW,REAL 1008,Server_1,Tag_9,3008,Created_tag_3008,AW,REAL 1009,Server_1,Tag_10,3009,Created_tag_3009,AW,REAL 1010,Server_1,Tag_11,3010,Created_tag_3010,AW,REAL 1011,Server_1,Tag_12,3011,Created_tag_3011,AW,DWORD 1012,Server_1,Tag_13,3012,Created_tag_3012,AW,DWORD 1013,Server_1,Tag_14,3013,Created_tag_3013,AR,DWORD 1014,Server_1,Tag_15,3014,Created_tag_3014,AR,DWORD 1015,Server_1,Tag_16,3015,Created_tag_3015,AR,DWORD 1016,Server_1,Tag_17,3016,Created_tag_3016,AR,DWORD 1017,Server_1,Tag_18,3017,Created_tag_3017,AR,DWORD 1018,Server_1,Tag_19,3018,Created_tag_3018,AR,DWORD 1019,Server_1,Tag_20,3019,Created_tag_3019,AR,DWORD 1020,Server_1,Tag_21,3020,Created_tag_3020,AR,DWORD 1021,Server_1,Tag_22,3021,Created_tag_3021,AW,BOOL 1022,Server_1,Tag_23,3022,Created_tag_3022,AW,BOOL 1023,Server_1,Tag_24,3023,Created_tag_3023,AW,BOOL 1024,Server_1,Tag_25,3024,Created_tag_3024,AW,BOOL 1025,Server_1,Tag_26,3025,Created_tag_3025,AW,BOOL 1026,Server_1,Tag_27,3026,Created_tag_3026,AW,DWORD 1027,Server_1,Tag_28,3027,Created_tag_3027,AR,DWORD 1028,Server_1,Tag_29,3028,Created_tag_3028,AR,DWORD 1029,Server_1,Tag_30,3029,Created_tag_3029,AR,DWORD 1030,Server_1,Tag_31,3030,Created_tag_3030,AR,REAL
我确定有一个 dup,您是根据指针的大小而不是指向的对象分配第二个缓冲区:
/* Allocate memory for each underlying server tag information */
ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data =
malloc(tags_count * sizeof(ua_server->underlying_server_data));
成为:
/* Allocate memory for each underlying server tag information */
ua_server[NUM_OF_UNDERLYING_SERVER].underlying_server_data =
malloc(tags_count * sizeof(*(ua_server->underlying_server_data)));
请注意,目前实际的代码*(ua_server->underlying_server_data
很糟糕,但 sizeof 是编译时,只是将代码用作模板来获取对象大小。
我有时希望有一个编译器警告"你要求指针的大小">
永远不要使用strcpy
,它是不安全的,因为它不执行任何形式的边界约束,并且只会在复制时坚持,直到它在源缓冲区中达到 0 字节。如果源缓冲区未(正确)以 0 结尾,或者源缓冲区的内容太长而无法放入目标,则会产生未定义的行为(崩溃或容易受到攻击)。
撇开固定大小字段的问题不谈,绝对有必要检查缓冲区操作的大小限制。您将使用的标准功能(尽管它仍然不完美)是strncpy
(请注意额外的n
)。需要注意的是,如果终止 0 字节不适合目标,strncpy
将省略它。
由于您的字段是固定大小的,因此您可以像这样使用它
strncpy(userver_info[location].SHM_Location, field, SHM_ADDR_LEN-1);
userver_info[location].SHM_Location[SHM_ADDR_LEN-1] = 0;
即它最多复制SHM_ADDR_LEN-1
个字节,并且始终在缓冲区的最末尾放置一个终止 0。