2009-10-12 4 views
2

Я пытаюсь создать матрицу с динамическими пропорциями и инициализировать его вот код, я использую для выделения памяти и инициализации:странно таНос поведение в C

int **matrix; 
//mem allocation 
matrix=(int*)malloc(sizeof(int*)*mat_w); 
for (i=0;i<mat_w;i++) 
    matrix[i]=(int)malloc(sizeof(int)*mat_h); 
//init 
for (i=0;i<mat_w;i++) 
    for (j=0;j<mat_h;j++) 
     matrix[i][j]=0; 

Это прекрасно работает, вопрос в том, , если я попытаюсь создать матрицу типа short - я получаю ошибку сегментации на первом проходе init.

Является ли это проблемой на языке C, или я делаю что-то неправильно?

Код для матрицы типа short:

short **matrix; 
//mem allocation 
matrix=(short*)malloc(sizeof(short*)*mat_w); 
for (i=0;i<mat_w;i++) 
    matrix[i]=(short)malloc(sizeof(short)*mat_h); 
//init 
for (i=0;i<mat_w;i++) 
    for (j=0;j<mat_h;j++) 
     matrix[i][j]=0; 

P.S .: Я уронил проверки безопасности, индексные переменные и граничные декларации для ясности кода.

Спасибо,
Alex

+3

Вы действительно кастинг возвращаемое значение из 'malloc' для целочисленных типов (а не указатели) в вашем коде? Кроме того, код отступа с 4 пробелами, чтобы отформатировать его как код. – outis

+0

Вам не нужна матрица = (int *) или = (короткая *)? – Locksfree

+0

А, я вижу, что случилось. Форматировщик употреблял лишние * символы. – outis

ответ

17

Ваши слепки для возвращаемого значения malloc() являются недействительными. Они должны быть int** и int* в первом случае и short** и short* во втором.

При разыгрывании возвращаемого значения malloc() к short, указателю вернулся получает усекается в short значения, а затем получает назначение на short* указатель, что дает значение указателя, указывающее на неправильное место памяти. Поэтому вы получаете ошибку сегментации, пытающуюся получить к ней доступ.

С int, вы получаете повезло, так как на вашей платформе, скорее всего sizeof(int)==sizeof(int*), так что указатель, возвращаемый malloc() отлитого в int не обрезается, и все это молча работает. Скорее всего, это сработает аналогично на 64-битной платформе.

Должен быть:

short **matrix; 
matrix=(short**)malloc(sizeof(short*)*mat_w); 
for (i=0;i<mat_w;i++) 
    matrix[i]=(short*)malloc(sizeof(short)*mat_h); 
for (i=0;i<mat_w;i++) 
    for (j=0;j<mat_h;j++) 
     matrix[i][j]=0; 

Если ваш код чистый C (не C++), вы можете опустить слепки, как и в отливке C от void* к любому другому типу указателя является действительным.

short **matrix; 
matrix = malloc(sizeof(short*)*mat_w); 
for (i=0;i<mat_w;i++) 
    matrix[i] = malloc(sizeof(short)*mat_h); 
for (i=0;i<mat_w;i++) 
    for (j=0;j<mat_h;j++) 
     matrix[i][j]=0; 
+0

спасибо, я вижу сейчас. – Alex

+0

Это один случай, когда я предпочитаю альтернативное использование 'sizeof()' - 'sizeof (matrix)' и 'sizeof (* matrix)' будет намного яснее здесь. –

+0

Кроме того, для любви к Skeet, пожалуйста, проверьте, что 'malloc()' не возвратил 'NULL' –

5

Вы бросаете ваш int** к int* возвращаемому значению таНоса (то же для краткости). malloc должны быть использованы как это:

matrix = (int**)malloc(sizeof(int*) * mat_w); 

или

matrix = (short**)malloc(sizeof(short*) * mat_w); 

То же самое для каждого распределения внутри матрицы:

matrix[i] = (int*)malloc(sizeof(int) * mat_h); 

или

matrix[i] = (short*)malloc(sizeof(short) * mat_h); 
0

sizeof(int) равна к шине ширине, в h конкретной системы. Вы пытаетесь поместить 32-битное (или 64 в зависимости от вашей платформы) значение адреса в 16-разрядную выделенную память.

Проверьте второй пример в столбце «Шашки». Это правильный и предпочтительный способ распределения памяти.

2

Да, вы делаете что-то неправильно.

int *matrix; 

означает, что matrix представляет собой массив целых чисел. Если вы хотите, чтобы быть массивом массивов целых чисел, вы должны объявить его как это:

int **matrix; 
//mem allocation 
matrix=(int**)malloc(sizeof(int*)*mat_w); 
for (i=0; i<mat_w; i++) 
    matrix[i]=(int*)malloc(sizeof(int)*mat_h); 
//init 
for (i=0; i<mat_w; i++) 
    for (j=0; j<mat_h; j++) 
     matrix[i][j]=0; 

Конечно, если вы заранее знаете, размеры матрицы, просто сделать это следующим образом:

int matrix[mat_w][mat_h]; 
//init 
for (i=0; i<mat_w; i++) 
    for (j=0; j<mat_h; j++) 
     matrix[i][j]=0; 
+0

+1, примечание о втором примере, там матрица хранится в стеке, иногда, если матрица достаточно велика , компилятор откажется создавать его в стеке, и возникнет необходимость выделить его в кучу. –

15

Какой компилятор вы используете, чтобы он не кричал на вас обо всех этих очевидных ошибках?

gcc -Wall подготовил пять предупреждающих сообщений с этим кодом.

#include <stdlib.h> 

int main() 
{ 
    int mat_w = 99; 
    int mat_h = 666; 
    int i; 
    int j; 

    int **imatrix; 
    short **smatrix; 
    //mem allocation 
    imatrix=(int*)malloc(sizeof(int*)*mat_w); 
    for (i=0;i<mat_w;i++) 
    imatrix[i]=(int)malloc(sizeof(int)*mat_h); 
    //init 
    for (i=0;i<mat_w;i++) 
    for (j=0;j<mat_h;j++) 
     imatrix[i][j]=0; 

    //mem allocation 
    smatrix=(short*)malloc(sizeof(short*)*mat_w); 
    for (i=0;i<mat_w;i++) 
    smatrix[i]=(short)malloc(sizeof(short)*mat_h); 
    //init 
    for (i=0;i<mat_w;i++) 
    for (j=0;j<mat_h;j++) 
     smatrix[i][j]=0; 
    return 0; 
} 

дает мне

malloc.c: In function 'main': 
malloc.c:13: warning: assignment from incompatible pointer type 
malloc.c:15: warning: assignment makes pointer from integer without a cast 
malloc.c:22: warning: assignment from incompatible pointer type 
malloc.c:24: warning: cast from pointer to integer of different size 
malloc.c:24: warning: assignment makes pointer from integer without a cast 
+2

Приобретен для обучения кого-то использованию '-Wall'. – Grandpa

6

Там серьезный урок ваш должны извлечь из этой ошибки. И он говорит следующее: никогда не произнесения результата 'malloc'.

Кроме того, это является частью более крупной надлежащей практики gudeline, что лучше всего следует по возможности: никогда не упоминает названия типов в коде, за исключением деклараций.

Это как ваш код должен был выглядеть с самого начала

int **matrix; 

    matrix = malloc(mat_w * sizeof *matrix); 
    for (i = 0; i < mat_w; i++) 
    matrix[i] = malloc(mat_h * sizeof *matrix[i]); 

    for (i = 0; i < mat_w; i++) 
    for (j = 0; j < mat_h; j++) 
     matrix[i][j] = 0; 

Обратите внимание, что для того, чтобы перейти от «межд» на «короткий» в этой версии вам просто нужно изменить декларацию " матрица "и ничего больше.

(Конечно, есть еще, что можно улучшить в этом коде, но я просто хотел, чтобы решить непосредственную причину ошибки.)

+0

Согласитесь, 100%. Если бы я мог, я бы увеличил это время. – caf

Смежные вопросы