使用strsep/strdup将C字符串操作为struct变量时的C分段错误

chr*_*rds -1 c segmentation-fault

我再次出现另一个分段错误(呻吟).

为了得到我现在的位置,我在这里有其他问题的帮助.

这个功能背后的想法是:

  • 传入一个字母*
  • 将传入的char*复制到堆上并指向此位置
  • 使用strsep根据','分隔符拆分"字符串"
  • 将这些拆分标记分配给结构变量
  • 释放指针

这是我传递给函数的内容:

gga_sentence结构:

typedef struct gga_sentence{

    const char *untouched_sentence;
    gsa_sentence *gsa;
    char *sentence_id;
    int time_stamp;
    double latitude;
    char north_south_id;
    double longitude;
    char east_west_id;
    int quality;
    int no_of_satellites;
    double horizontal_dillution;
    double altitude;
    char altitude_units;
    double geodial_seperation;
    char geodial_seperation_units;
    char* age_of_data_in_seconds;
    char *checksum;

}gga_sentence;
Run Code Online (Sandbox Code Playgroud)

gga_parsed是:

    gga_sentence *ggas_parsed;
    ggas_parsed = malloc(10*sizeof(gga_sentence));
Run Code Online (Sandbox Code Playgroud)

其中line是char [100],使用从文件读取的行填充,这很好.

strncpy(&ggas_parsed[number_of_gga_parsed].untouched_sentence, line, strlen(line));
            printf("GGA UNTOUCHED: %s", &ggas_parsed[number_of_gga_parsed].untouched_sentence);
Run Code Online (Sandbox Code Playgroud)

initiate_gga_values(&ggas_parsed [number_of_gga_parsed],&ggas_parsed [number_of_gga_parsed] .untouched_sentence);

上面的printf声明:

printf("GGA UNTOUCHED: %s", &ggas_parsed[number_of_gga_parsed].untouched_sentence);
Run Code Online (Sandbox Code Playgroud)

生产:

GGA UNTOUCHED: $GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72
Run Code Online (Sandbox Code Playgroud)

所以当我通过以下方式将其传递给上述功能时:

initiate_gga_values(&ggas_parsed[number_of_gga_parsed], &ggas_parsed[number_of_gga_parsed].untouched_sentence);
Run Code Online (Sandbox Code Playgroud)

函数itsef定义为:

void initiate_gga_values(gga_sentence* gga_ptr, const char* sentence){

    char *temp_sentence, *second_temp_ptr;
    char *token;
    int token_no = 0;

    temp_sentence = strdup(sentence);
    second_temp_ptr = temp_sentence;

    printf("TS: %s", temp_sentence);
    printf("2nd: %s", second_temp_ptr);

    token = strsep (&second_temp_ptr,",");

    while (token != NULL) {
        /*if a sentence has missing data then make that clear by settings it's value to
         * <EMPTY>*/
        if(strlen(token)==0){
            token = "<EMPTY>";
        }
        switch(token_no){
        case 0:
            gga_ptr->sentence_id = token;
            //printf("%s,",gga_ptr->sentence_id);
            break;
        case 1:
            /*atoi converts a string to an int, well a c string anyways so a char* */
            gga_ptr->time_stamp = atoi(token);
            //printf("%d,",gga_ptr->time_stamp);
            break;
        case 2:
            /*strtod coverts a string to a double, well a c string anyways so a char* */
            gga_ptr->latitude = strtod(token, NULL);
            //printf("%f,",gga_ptr->latitude);
            break;
        case 3:
            gga_ptr->north_south_id = *token;
            //printf("%c,",gga_ptr->north_south_id);
            break;
        case 4:
            gga_ptr->longitude = strtod(token, NULL);
            //printf("%f,",gga_ptr->longitude);
            break;
        case 5:
            gga_ptr->east_west_id = *token;
            //printf("%c,",gga_ptr->east_west_id);
            break;
        case 6:
            gga_ptr->quality = atoi(token);
            //printf("%d,",gga_ptr->quality);
            break;
        case 7:
            gga_ptr->no_of_satellites = atoi(token);
            //printf("%d,",gga_ptr->no_of_satellites);
            break;
        case 8:
            gga_ptr->horizontal_dillution = strtod(token, NULL);
            //printf("%f,",gga_ptr->horizontal_dillution);
            break;
        case 9:
            gga_ptr->altitude = strtod(token, NULL);
            //printf("%f,",gga_ptr->altitude);
            break;
        case 10:
            gga_ptr->altitude_units = *token;
            //printf("%c,",gga_ptr->altitude_units);
            break;
        case 11:
            gga_ptr->geodial_seperation = strtod(token, NULL);
            //printf("%f,",gga_ptr->geodial_seperation);
            break;
        case 12:
            gga_ptr->geodial_seperation_units = *token;
            //printf("%c,",gga_ptr->geodial_seperation_units);
            break;
        case 13:
            /*This is never used in the sentenced given*/
            gga_ptr->age_of_data_in_seconds = token;
            //printf("%s,",gga_ptr->age_of_data_in_seconds);
            break;
        case 14:
            gga_ptr->checksum = token;
            //printf("%s",gga_ptr->checksum);
            break;
        }
        token_no++;
        token = strsep (&second_temp_ptr, ",");

    }

    printf("untouched: %s\n", sentence);
    printf("Second print of TS: %s\n", temp_sentence);
    printf("second print of second_temp: %s\n", second_temp_ptr);

    free(temp_sentence);
    exit(1); //DBUGGING PURPOSES
}
Run Code Online (Sandbox Code Playgroud)

该函数的输出是:

TS: $GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72
2nd: $GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72
untouched: $GPGGA,151019.00?(m
Second print of TS: $GPGGA
second print of second_temp: (null)
Run Code Online (Sandbox Code Playgroud)

所以如果我添加这个printf语句:

printf("testing untouched: %s", gga_ptr->untouched_sentence);
Run Code Online (Sandbox Code Playgroud)

进入initiate_gga_values函数,就在退出(1)之前,我得到了一个分段错误.使用打印gga_ptr-> untouched_sentence的额外打印行再次运行代码的输出产生:

GGA UNTOUCHED: $GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72
TS: $GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72
2nd: $GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72
untouched: $GPGGA,151019.00??b
Second print of TS: $GPGGA
second print of second_temp: (null)
Segmentation fault (core dumped)
Run Code Online (Sandbox Code Playgroud)

我不知道发生了什么事.

有任何想法吗?

干杯,克里斯.

Dou*_*der 5

这是错的:

const char* untouched_sentence;

strncpy(&ggas_parsed[number_of_gga_parsed].untouched_sentence, line, strlen(line));
            printf("GGA UNTOUCHED: %s", &ggas_parsed[number_of_gga_parsed].untouched_sentence);
Run Code Online (Sandbox Code Playgroud)

第一个参数strncpy应该是一个缓冲区来放置副本,你已经给它一个指向你的结构的指针.第三个参数应该是目标缓冲区的大小,而不是输入!

你需要这样做:

char* untouched_sentence;

ggas_parsed[number_of_gga_parsed].untouched_sentence = malloc(<size>);
Run Code Online (Sandbox Code Playgroud)

哪里<size>需要,如果你担心排长队来的strlen(线),还有一些限制.

然后:

strncpy(ggas_parsed[number_of_gga_parsed].untouched_sentence, line, strlen(line));
printf("GGA UNTOUCHED: %s",ggas_parsed[number_of_gga_parsed].untouched_sentence);
Run Code Online (Sandbox Code Playgroud)

我认为你需要从一个更简单的例子开始,以了解内存管理.