سؤال

أحاول إنشاء مصفوفة ذات أبعاد ديناميكية وتهيئتها هنا هو الكود الذي أستخدمه لتخصيص الذاكرة والتهيئة:

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:

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;

ملاحظة: لقد أسقطت عمليات فحص السلامة ، ومتغيرات الفهرس وإعلانات الحدود لوضوح الكود.

شكرًا،
أليكس

هل كانت مفيدة؟

المحلول

الممثلين الخاص بك لقيمة إرجاع 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 string from 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;

نصائح أخرى

ما هو المترجم الذي تستخدمه أنه لا يصرخ عليك حول كل هذه الأخطاء الواضحة؟

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

هناك درس خطير يجب أن تتعلمه من هذا الخطأ. وتقول ما يلي: لم يلقي أبدًا نتيجة "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;

لاحظ أنه من أجل التبديل من "int" إلى "قصيرة" في هذا الإصدار ، تحتاج فقط إلى تغيير إعلان "المصفوفة" ولا شيء آخر.

(بالطبع ، هناك المزيد يمكن تحسينه في هذا الرمز ، لكنني أردت فقط معالجة السبب المباشر للخطأ.)

أنت تلقي بك int** إلى int* قيمة إرجاع malloc (نفس الشيء لفترة قصيرة). 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);

نعم ، أنت تفعل شيئًا خاطئًا.

 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; 

sizeof(int) يساوي عرض الحافلة للنظام المعين. أنت تحاول وضع 32 بت (أو 64 اعتمادًا على النظام الأساسي الخاص بك) قيمة العنوان إلى ذاكرة مخصصة 16 بت.

تحقق من المثال الثاني في Post Chequers. هذه هي الطريقة الصحيحة والمفضل لتخصيص الذاكرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top