c语言 - 由于字符串复制而导致的分段错误



在下面的代码中,代码在第四次执行 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。

相关内容

  • 没有找到相关文章

最新更新