سؤال

أريد تخزين سلسلة في الذاكرة وقراءتها لاحقًا:

$$->desc.constant->base.id =  (char*)malloc(200);
sprintf($$->desc.constant->base.id, "%f", $1);
printf("->%s\n", $$->desc.constant->base.id); //LINE A
printf("->%i\n", $$->desc.constant); //LINE B

//SOME OTHER CODE

//Then, later on in a function call:

printf("%i", expr->desc.constant); // LINE D
printf("%s", expr->desc.constant->base.id); // LINE C

على الرغم من أن السطر B والسطر D يعرضان نفس العنوان، إلا أن الطباعة في السطر C تفشل بسبب خطأ التجزئة.ماذا ينقصني؟

أي مساعدة سيكون حقا موضع تقدير!

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

المحلول

printf("->%i\n", $$->desc.constant); //LINE B

وهذا غير صحيح. كما تظهر لك خط قبل أن constant هو في الواقع مؤشر، لا يمكنك التعامل معها كما لو كانت من نوع int. لم يكن لديهم necassarily نفس محاذاة sizeof و. استخدام تنسيق المستخدمة لvoid*. وسوف تتناول الذاكرة الناتج بشكل صحيح:

printf("->%p\n", (void*)$$->desc.constant); //LINE B

نصائح أخرى

  1. دائماً يفحص mallocقيمة الإرجاع.
  2. sprintf -> snprintf
  3. "%f" -> "%.*g"

هنا مثال:

/** $ gcc print_number.c -o print_number */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
  const char* number_format = "%.*g";
  const int ndigits = 15;
  assert(ndigits > 0);
  const int maxlen = ndigits + 8 /* -0.e+001, Infinity */ + 1 /* '\0' */;

  char *str = malloc(maxlen);
  if (str == NULL) {
    fprintf(stderr, "error: malloc\n");
    exit(1);
  }    

  double number = 12345678901234567890.123456789012345678901234567890;
  /** `number = 0/0` crashes the program */;

  printf("number: %f\t", number);

  int len_wouldbe = snprintf(str, maxlen, number_format, ndigits, number);
  assert(len_wouldbe < maxlen);

  printf("%s\n", str);
  return 0;
}

انتاج:

number: 12345678901234567000.000000 1.23456789012346e+19

وربما بين وقت قطعتين من التعليمات البرمجية التي قمت منذ freed السلسلة؟

$$->desc.constant->base.id =  (char*)malloc(200);
sprintf($$->desc.constant->base.id, "%f", $1);
printf("->%s\n", $$->desc.constant->base.id); //LINE A
printf("->%i\n", $$->desc.constant); //LINE B

//SOME OTHER CODE
// which happens to do
free($$->desc.constant->base.id);

printf("%i", expr->desc.constant); // LINE D
printf("%s", expr->desc.constant->base.id); // crash

ونظرا إلى أن البرنامج ينتج خطأ تجزئة، وأعتقد أن المشكلة هي الأكثر احتمالا أن بنية المعينة (وأشار إلى) من خلال expr->desc.constant تم استخدامها منذ تم تخصيص مساحة، أو ربما الفضاء لم يكن تخصيص حقا على الإطلاق.

والرمز المعارض المختلفة خطايا طفيف، مثل استخدام sprintf() بدلا من snprintf()، وتخصيص مسوغ 200 بايت لتمثيل سلسلة من عدد النقطة العائمة. (أنت من المستبعد جدا الحاجة إلى الكثير من الفضاء، وإذا قمت بذلك، يجب على الارجح سماح لا يقل عن 100 الأرقام أكثر مما لديك، لأن نطاق الأس للأرقام النقطة العائمة عادة +/- 308، والسبب الوحيد الذي 'د تحتاج 200 حرف هو السماح لأعداد كبيرة بشكل لا يصدق أو صغيرة بشكل لا يصدق.)

ولقد أظهرت أن نقاط $$->desc.constant إلى نفس المكان، ولكنك لم يظهر كيف يتم تخصيص تلك المساحة. يمكنك ثم تخصيص مساحة السلسلة في $$->desc.constant->base.id، دون تخصيص بوضوح مساحة للbase.

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