fclose () تسبب خطأ تجزئة
-
22-07-2019 - |
سؤال
ولدي ملف نصي المفصول أنني تحليل. يحتوي العمود الأول سلاسل من chrX
الشكل، حيث يدل X
مجموعة من السلاسل، على سبيل المثال، "1"، "2"، ...، "X"، "Y".
وهذه هي كل تخزينها في char*
دعا chromosome
، كما يتم تحليل الملف.
ويتم فرز ملف نصي على العمود الأول lexicographically، أي، وسوف يكون لديك عدد الصفوف بدءا من "chr1"، ثم "chr2"، وما إلى ذلك.
وفي كل دخول "chrX"، ولست بحاجة لفتح ملف آخر مقترن هذا الموضوع:
FILE *merbaseIn;
// loop through rows...
if (chromosome == NULL)
openSourceFile(&chromosome, fieldArray[i], &merbaseIn, GENPATHIN);
else {
if (strcmp(chromosome, fieldArray[i]) != 0) { // new chromosome
fclose(merbaseIn); // close old chromosome FILE ptr
free(chromosome); // free old chromosome ptr
openSourceFile(&chromosome, fieldArray[i], &merbaseIn, GENPATHIN); // set up new chromosome FILE ptr
}
}
// parse row
ولدي openSourceFile
وظيفة التي تم تعريفها على النحو التالي:
void openSourceFile (char** chrome, const char* field, FILE** filePtr, const char *path) {
char filename[100];
*chrome = (char *) malloc ((size_t) strlen(field));
if (*chrome == NULL) {
fprintf(stderr, "ERROR: Cannot allocate memory for chromosome name!");
exit(EXIT_FAILURE);
}
strcpy(*chrome, field);
sprintf(filename,"%s%s.fa", path, field);
*filePtr = fopen(filename, "r");
if (*filePtr == NULL) {
fprintf(stderr, "ERROR: Could not open fasta source file %s\n", filename);
exit(EXIT_FAILURE);
}
}
والمشكلة هي أن طلبي إنهاء مع خطأ الإنقسام الانتقال من الكروموسوم الأول إلى الثاني (من chr1
إلى chr2
) في السطر التالي، حيث أن أغلق أول ملف كروموسوم التي فتحت:
fclose(merbaseIn);
وأنا أعلم أنني لست يمر fclose
مؤشر NULL، لأن حتى صدع الإنقسام، وأنا قراءة البيانات من هذا الملف. حتى أستطيع أن التفاف ذلك في مشروطة وأنا لا يزال الحصول على خطأ:
if (merbaseIn != NULL) {
fclose(merbaseIn);
}
وعلاوة على ذلك، وأنا أعلم أعمال openSourceFile
(على الأقل بالنسبة chr1
، عند إعداد مؤشر الملف الأول من FILE*
) لطلبي يوزع صفوف chr1
ويقرأ البيانات من ملف مصدر FILE*
بشكل صحيح.
وماذا عن هذه الدعوة fclose
الذي يسبب خطأ الإنقسام أن يحدث؟
المحلول
valgrind --db-attach=yes --leak-check=yes --tool=memcheck --num-callers=16 --leak-resolution=high ./yourprogram args
ومن المرجح جدا هو سبب segfault من قبل تلف الذاكرة على كومة، وليس أي شيء يؤثر على السكان المحليين. Valgrind سوف تظهر لك على الفور أول وصول الخطأ التي تقوم بها.
وتحرير: تم إيقاف الخيار --db-attach
إلى valgrind
منذ الإفراج 3.10.0 في عام 2014. ويشير إطلاق الدولة:
The built-in GDB server capabilities are superior and should be used
instead. Learn more here:
http://valgrind.org /docs/manual/manual-core-adv.html#manual-core-adv.gdbserver
نصائح أخرى
وخطأ واحد أنا لاحظت هو هذا السطر:
*chrome = (char *) malloc ((size_t) strlen(field));
والتي ينبغي أن تكون:
*chrome = (char *) malloc ((size_t) strlen(field)+1);
وذلك لأن سلسلة لديها إغلاق 0 في نهاية التي لديك أيضا لإفساح المجال ل
وأفضل تخمين هو أن أي جزء آخر من التعليمات البرمجية هي الذاكرة المفسدة من خلال تجاوز سعة المخزن المؤقت أو خلل مماثل.
وعلى الرغم من المرجح أن يكون سبب، لديك حالة تجاوز المحتملة في مجموعة اسم الملف الخاص بك عندما يتجاوز اسم الملف الكامل 100 حرف.
وأود أن أقترح استخدام مصحح لمراقبة التغييرات في الموقع الذاكرة المستخدمة من قبل متغير merbaseIn.
عام المؤشر مشكلة
وC هي لغة عظيمة لكنها لا تتطلب منك لا هزم الذاكرة الخاصة بك. إلى جانب مشكلة لوحظ سابقا حيث malloc هو 1 بايت القصير، قد يكون لديك مشاكل مؤشر أخرى.
وأود أن أقترح باستخدام المصحح ذاكرة . في الماضي، كان الكهربائية سياج شعبية نوعا ما ولكن في هذه الأيام I <لأ href = "HTTP: //en.wikipedia.org/wiki/Valgrind "يختلط =" نوفولو noreferrer "> سماع المزيد عن valgrind . هناك الكثير من الخيارات الأخرى.
وبالإضافة إلى الخطأ وجدت من قبل اللاعب Reinier ، وأظن أن:
free(chromosome);
يجب أن يتبعها:
chromosome = NULL;
ومن أجل منع استخدام محتمل لقيمة لم تعد صالحة.
لماذا هذا FILE ** filePtr إلا إذا كان هذا FILE * filePtr سيكون كافيا؟ مجرد التفكير ...
وvalgrind
مع memcheck
هو بالتأكيد الأداة المناسبة لاكتشاف سبب خطأ تجزئة. لاستخدام المصحح مع valgrind
، لاحظ أن الخيار --db-attach
إلى valgrind
تم إهمال منذ صدر Valgrind 3.10.0 في عام 2014. ويشير إطلاق الدولة:
The built-in GDB server capabilities are superior and should be used
instead. Learn more here:
http://valgrind.org /docs/manual/manual-core-adv.html#manual-core-adv.gdbserver
ومراجعة كل مكان استخدمته على "malloc" ثم نرى ما اذا كان ارتكب خطأ.
وعلى سبيل المثال، كنت في وضع خطوط قراءة من ملف إلى شار **، لكنني غير صحيح malloced على النحو التالي:
my_list = malloc(sizeof(char) * num_lines_found_in_file);
وعندما كان ينبغي أن يكون:
my_list = malloc(sizeof(char*)* num_lines_found_in_file);