C分段错误,任何人都可以帮我找出原因吗?

时间:2014-03-10 19:05:02

标签: c segmentation-fault

我使用以下代码在C中拆分char数组:

    char line[100];
int number_of_gga_parsed = 0;
int gga_blocks_allocated;
    gga_sentence *ggas_parsed;
    gsa_sentence gsa;
    gsv_sentence gsv;


    ggas_parsed = malloc(10*sizeof(gga_sentence));
    gga_blocks_allocated = 10;

    if(ggas_parsed == NULL){

        printf("error allocating memory, system exiting.\n");
        exit(EXIT_FAILURE);
    }

    while(fscanf(stream, "%s", line)!= EOF){

    strcpy((ggas_parsed + number_of_gga_parsed)->untouched_sentence, line);

    initiate_gga_values((ggas_parsed + number_of_gga_parsed),(ggas_parsed + number_of_gga_parsed)->untouched_sentence);

}

initiate_gga_values功能:

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

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

    /*Copy the gga_sentence into the temp_sentence char array*/
    strcpy(temp_sentence, sentence);


    token = strsep (temp_sentence,",");

    while (token != NULL) {
        switch(token_no){
        case 0:
            gga_ptr->sentence_id = token;
            break;
        case 1:
            /*atoi converts a string to an int, well a c string anyways so a char* */
            gga_ptr->time_stamp = atoi(token);
            break;
        case 2:
            /*strtod coverts a string to a double, well a c string anyways so a char* */
            gga_ptr->latitude = strtod(token, NULL);
            break;
        case 3:
            gga_ptr->north_south_id = (char)token;
            break;
        case 4:
            gga_ptr->longitude = strtod(token, NULL);
            break;
        case 5:
            gga_ptr->east_west_id = (char)token;
            break;
        case 6:
            gga_ptr->quality = atoi(token);
            break;
        case 7:
            gga_ptr->no_of_satellites = atoi(token);
            break;
        case 8:
            gga_ptr->horizontal_dillution = strtod(token, NULL);
            break;
        case 9:
            gga_ptr->altitude = strtod(token, NULL);
            break;
        case 10:
            gga_ptr->altitude_units = (char)token;
            break;
        case 11:
            gga_ptr->geodial_seperation = strtod(token, NULL);
            break;
        case 12:
            gga_ptr->geodial_seperation_units = (char)token;
            break;
        case 13:
            gga_ptr->age_of_data_in_seconds = strtod(token, NULL);
            break;
        case 14:
            gga_ptr->checksum = token;
            break;
        }
        token_no++;
        token = strsep (temp_sentence, ",");

         }
}

char数组包含以下信息:

$GPGGA,151019.000,5225.9627,N,00401.1624,W,1,09,1.0,38.9,M,51.1,M,,0000*72

但是当上面的代码运行时,我得到一个分段错误:

Segmentation fault (core dumped)

gga struct:

typedef struct gga_sentence{

    char untouched_sentence[100];
    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;
    double age_of_data_in_seconds;
    char *checksum;

}gga_sentence;

分段错误发生在函数initiate_gga_values函数完成之前,甚至是真正启动的。这意味着我假设gga_sentences的mallocing存在问题,但我看不到哪里!

这是我第一次使用strsep,所以毫无疑问我做错了。

gdb错误消息:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7de4103 in _dl_lookup_symbol_x (undef_name=0x4004d8 "strlen", undef_map=0x7ffff7ffe268, 
    ref=ref@entry=0x7fffffffdbb8, symbol_scope=0x302e312c362e312c, version=0x7ffff7ff9a08, 
    type_class=type_class@entry=1, flags=1, skip_map=skip_map@entry=0x0) at dl-lookup.c:733
733 dl-lookup.c: No such file or directory.

干杯, 克里斯。

3 个答案:

答案 0 :(得分:3)

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

/*Copy the gga_sentence into the temp_sentence char array*/
strcpy(temp_sentence, sentence);

您没有为temp_sentence分配任何内存来保存复制的字符串

答案 1 :(得分:0)

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

strsepchar**作为第一个参数。

答案 2 :(得分:0)

您正在将sentence复制到未初始化的内存:

char *temp_sentence;

/* ... */

strcpy(temp_sentence, sentence);

temp_sentence是一个未初始化的指针,指向某个随机位置,但不指向任何额外的内存。要解决此问题,您可以在堆栈上分配一定数量的字符,例如:

char temp_sentence[100];

strncpy(temp_sentence, sentence, sizeof(temp_sentence) - 1);

这可能会缩短您的字符串。另一种方法是在堆上分配输入字符串的副本:

char *temp_sentence = strdup(sentence);

在这种情况下,在从函数返回之前,必须使用free(temp_sentence)释放已分配的内存。在任何一种情况下,您都需要一个可以传递给strsep的第二个指针:

char *ptr = temp_sentence;

此指针需要可修改,因此您无法使用数组。如果临时字符串分配有strdup,则需要保留原始指针,以便释放内存。

编辑:正如Arjun Sreedharan已经指出的那样,您应该将指向char的指针作为strsep的第一个参数传递。这样,指针就会更新并引用尚未解析的其余字符串。

指针类型不匹配应该真正给出警告信息。你启用了警告吗?

无论如何,这里有一个简短的工作示例,说明你想要做什么,但没有实际的解析:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
    const char* sentence = "$GPGGA,151019.000,5225.9627,N,"
                            "00401.1624,W,1,09,1.0,38.9,M,"
                            "51.1,M,,0000*72";

    char *tmp = strdup(sentence);   // modifiable copy
    char *p = tmp;                  // pointer into copy for strsep
    char *token;
    int token_no = 0;

    token = strsep(&p, ",");
    while (token != NULL) {
        printf("%d: '%s'\n", token_no, token);
        token_no++;
        token = strsep(&p, ",");
    }

    free(tmp);                      // release ressources of copy
    return 0;
}