2015-09-12 3 views
0

Я пытаюсь понять таНос, но я получаю «ошибку сегментации: 11» с этим фрагментом кода:C таНос (ошибка сегментирования: 11)

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

int main() 
{ 
    int i = 0, j = 0; 
    char ** ptr = (char **) malloc(sizeof(char*)); 

    for(i = 0; i < 5; i++) 
    { 
     for(j = 0; j < 10; j++) 
      ptr[i][j] = 'a'; 

     printf("%s\n", ptr[i]); 
    } 

    return 0; 
} 

я думал, что не было достаточно байт выделено так, я сделал malloc(sizeof(char*) * 100, но дает мне ту же ошибку. Что я здесь не понимаю?

+1

'ptr [i]' - указатель, но на что он указывает? – Quentin

+0

Не указывает ли оно на начало выделенной памяти? Если я просто делаю 'char * ptr = (char *) malloc (sizeof (char))' и убираю второй оператор цикла, он отлично работает. – neby

+0

'ptr', но' ptr [0] 'не делает. – Olaf

ответ

4

Когда вы выделяете 2D-массив, вам также необходимо выделить отдельные подмассивы. Кроме того, вам нужно сказать, сколько элементов вы хотите иметь. Для этого нужно умножить желаемое количество на количество элементов, например:

char ** ptr = (char **) malloc(5*sizeof(char*)); 
// Size=5 ---------------------^ 
for(int i = 0; i < 5; i++) { 
    ptr[i] = malloc(11*sizeof(char)); 
    // sizeof(char) is always 1, so the multiplication above is redundant. 
    // You need 11 elements for ten characters 
    for(int j = 0; j < 10; j++) { 
     ptr[i][j] = 'a'; 
    } 
    // don't forget to null-terminate the string: 
    ptr[i][10] = '\0'; 
    printf("%s\n", ptr[i]); 
} 
+0

Спасибо, Это проясняет много путаницы. – neby

2

Ваш код полностью перепутались в каждом аспекте!

1) вы выделили память точно для 1 указателя на нее. Это означает, что вы можете получить доступ к ptr [0], но не ptr [1] ... ptr [4], как вы пытаетесь это сделать.

2) вы никогда ничего не выделяете для элементов в ptr [i].

3) вы пытаетесь напечатать строку ptr [i], которая (даже если ваше распределение будет правильным) никогда не будет завершено.

4) хотя это, очевидно, только тест для новичков, никогда не забывайте освобождать свою память !!!!

Чтобы достичь чего-то близко к тому, коду sampel описывает вы могли бы сделать:

int main() 
{ 
int i,j; 
char ** ptr = malloc(5 * sizeof(char*)); /* an array of 5 elements of type char* */ 
for(i = 0; i < 5; i++) 
{ 
    ptr[i] = malloc(11*sizeof(char)); /* The element i of the array is an array of 11 chars (10 for the 'a' character, one for the null-termination */ 
    for(j = 0; j < 10; j++) 
     ptr[i][j] = 'a'; 
    ptr[i][10] = '\0'; /* strings need to be null terminated */ 

    printf("%s\n", ptr[i]); 
} 
// free your memory! 
for (i=0; i<5; i++) 
{ 
    free(ptr[i]); 
} 
free(ptr); 

return 0; 
+0

Спасибо, никогда не знали о 'free()'. Я должен использовать его, как только я закончил, используя любой указатель, инициализированный с помощью malloc? – neby

+0

malloc «хранит» память. Если вы не освободите его, ваша программа использует все больше и больше памяти, не отдавая ее обратно в операционную систему. Каждый «malloc()» должен иметь соответствующий «free()» где-то в коде. Кроме того, это не является реальной проблемой в вашем коде, потому что память выпущена в любом случае, как только программа завершается, вы должны немедленно изучить эту практику. Всякий раз, когда вы вызываете malloc, вы должны иметь свободный доступ. Что/где «соответствие» зависит от вашего кода. –

+0

Это имеет смысл. Спасибо за всю информацию! – neby

-1

Другим способом выделения памяти является:

char (*ptr)[11] = malloc(sizeof(char[5][11])); 

for(i = 0; i < 5; i++) 
{ 
    for(j = 0; j < 10; j++) 
     ptr[i][j] = 'a'; 

    ptr[i][10] = 0; 
    printf("%s\n", ptr[i]); 
} 

free(ptr); 

кажется меньше хлопот использовать одну распределение чем использовать много ассигнований, если у вас нет насущной причины сделать последнее.

+0

немного упс. объявили 11 указателей на символ, но только установили первый. – user3629249

+0

@ user3629249 нет, это 1 указатель на массив из 11 символов. Вы описываете 'char * ptr [11];' –