2013-03-10 1 views
1
int main(int argc, char **argv){ 
    char *str = argv[1]; 
    size_t len = strlen(str); 
    char *dst = calloc(len+1, sizeof(char)); 
    int i; 
    for(i=len-1; i>=0; i--){ 
     memcpy(dst, str+i, 1); 
     dst++; 
    } 
    *(++dst) = '\0'; 
    printf("%s\n", dst); 
    free(dst); 
    return 0; 
} 

проверки ошибок опущено для получения дополнительной читаемости
Я не понимаю, почему я получил Segfault с этим сообщением: «GLibC свободный(): недопустимый указатель:»
Я пытаюсь написать небольшую программу, которая обращает строку с помощью указателей, но:
1) последний printf ничего не печатает;
2) я получил Segfaultсегментации при освобождении указателя при движении задним ходом строки в C

+3

Вы меняете значение 'dst'. Вам нужно освободить начало буфера, который вы выделили. – Joe

ответ

3

проблема заключается в том, что вы меняете указатель в вычислениях.
попробовать использовать temp или original для этого типа:

int main(int argc, char **argv){ 
    char *str = argv[1]; 
    size_t len = strlen(str); 
    char *dst = calloc(len+1, sizeof(char)); 
    char *origDst = dst; 
    int i; 
    for(i=len-1; i>=0; i--){ 
     memcpy(dst, str+i, 1); 
     dst++; 
    } 
    *(dst) = '\0'; 
    printf("%s\n", origDst); 
    free(origDst); 
    return 0; 
} 
+1

Спасибо: D Я думал, что все это время xD – polslinux

+0

Я не понимаю, почему ответ, который предполагает использование 'memcpy()' для копирования одного байта, сохраняется. – 2013-03-10 15:49:54

+0

Мое удовольствие (-: –

9

Вы:

char *dst = calloc(len+1, sizeof(char)); 
    /* ... */ 
    *(++dst) = '\0'; 
    /* ... */ 
    free(dst); 

Вы должны free указатель, который был выделен на malloc/calloc. Здесь вы изменили его. Сделайте копию, чтобы вы могли free после.

+1

Я чувствую, что '* (++ dst) = '\ 0';' может быть '* dst = '\ 0';' потому что указатель уже увеличивается в цикле. в противном случае будет двойной приращение – Ganesh

+0

Спасибо! Вы решили мою проблему! :) – polslinux

1

Есть 2 точки, которые необходимо учитывать. Во-первых, сделать копию исходного указателя, выделенную calloc, как уже сообщалось ouah. Другим моментом является устранение приращения указателя при сохранении NULL, то есть *(++dst) = '\0'; должно быть *dst = '\0';. С этими двумя изменениями я могу запускать вашу программу без каких-либо проблем.

+0

Приятная уловка на '* (++ dst) = '\ 0';' (+1) –