سؤال

بقدر ما أستطيع أن أقول ، Asprintf يدعو malloc. إذا استبدلت Malloc بـ Boehm GC ، فإن دعوة إلى Asprintf لا تزال تدعو Malloc التقليدية - على الأقل هذا ما تخبرني به Valgrind:

ها هو ماكرو مالوك:

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

#include <gc.h>
#define malloc(n)    GC_MALLOC(n)
#define calloc(m,n)  GC_MALLOC((m)*(n))
#define realloc(p,n) GC_REALLOC((p),(n))

typedef char * string;

وهنا تقرير فالغريند:

hopcroft:didactic_scheme(flexible_strings) scotttaylor$ valgrind --suppressions=./boehm-gc.suppressions --leak-check=full bin/escheme -e 1
==16130== Memcheck, a memory error detector
==16130== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==16130== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==16130== Command: bin/escheme -e 1
==16130== 
--16130-- bin/escheme:
--16130-- dSYM directory is missing; consider using --dsymutil=yes
1==16130== 
==16130== HEAP SUMMARY:
==16130==     in use at exit: 4,312 bytes in 3 blocks
==16130==   total heap usage: 3 allocs, 0 frees, 4,312 bytes allocated
==16130== 
==16130== 128 bytes in 1 blocks are definitely lost in loss record 2 of 3
==16130==    at 0x100012D75: malloc (vg_replace_malloc.c:236)
==16130==    by 0x1000918EC: asprintf (in /usr/lib/libSystem.B.dylib)
==16130==    by 0x1000013FA: printInt (in bin/escheme)
==16130==    by 0x100001D38: print (in bin/escheme)
==16130==    by 0x100001DC5: main (in bin/escheme)
==16130== 
==16130== LEAK SUMMARY:
==16130==    definitely lost: 128 bytes in 1 blocks
==16130==    indirectly lost: 0 bytes in 0 blocks
==16130==      possibly lost: 0 bytes in 0 blocks
==16130==    still reachable: 4,184 bytes in 2 blocks
==16130==         suppressed: 0 bytes in 0 blocks
==16130== Reachable blocks (those to which a pointer was found) are not shown.
==16130== To see them, rerun with: --leak-check=full --show-reachable=yes
==16130== 
==16130== For counts of detected and suppressed errors, rerun with: -v
==16130== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 66 from 13)

إليك الرمز الذي تأتي فيه مكالمة Malloc من:

static string printInt(Object self) {
  string str;
  asprintf(&str, "%lu", getValueInt(self));
  return str;
}

قد يكون الحل البديل هو استخدام ASPRINTF ، ثم استخدم Malloc لنسخه بحيث يتم استخدام ماكرو Malloc بدلاً من الوظيفة البدائية:

static string printInt(Object self) {
  string tmp;
  string str;

  asprintf(&tmp, "%lu", getValueInt(self));
  str = calloc(sizeof(string), strlen(tmp) + 1);

  strcpy(str, tmp);
  free(tmp);

  return str;
}

هذا يبدو سخيفًا - إنه ينطوي على مجموعة من النسخ غير الضرورية ويحدث أيضًا أن يكون رمزًا مؤلمًا. هل هناك طريقة آمنة لاستخدام ASPRINTF ومكتبات النظام الأخرى التي قد تتصل بـ Malloc الأصلي مع الاستمرار في استخدام Boehm GC؟ هل هناك بديل لـ Asprintf يجب أن أستخدمه بدلاً من ذلك؟

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

المحلول

snprintf إرجاع عدد الشخصيات التي كان من الممكن أن تكون مكتوبة لو كان المخزن المؤقت المقدم كبيرًا بما يكفي. يمكنك استدعاء هذه الطريقة مرتين (مرة واحدة للحصول على حجم المخزن المؤقت المناسب ثم مرة أخرى مع مخزن مؤقت كبير بما يكفي للحصول على الإخراج) ، ومع ذلك ربما سيكون أقل كفاءة من مجرد نسخ إخراج asprintf في المخزن المؤقت القابل للتحصيل. فيما يلي مثال يحتوي على رمز يخصص مخزن مؤقت كبير بما يكفي لاحتواء القيمة القصوى للأنظمة الطويلة غير الموقعة لأنظمة 32 بت. على الأنظمة التي لا يوجد فيها مساحة كافية ، يتم إعادة تخصيص المخزن المؤقت وإعادة تنسيقه.

#include <limits.h>

...

unsigned long intValue = getValueInt(self);
size_t maxLength = 11; // heuristic
char *buf = malloc(maxLength);

int result = snprintf(buf, maxLength, "%lu", intValue);
if (result > maxLength)
{
    // shouldn't ever get here, but just in case the buffer is too small
    // we reallocate it to the correct size and try again.
    buf = malloc(result);
    snprintf(buf, result, "%lu", intValue);
}

return buf;

نصائح أخرى

وفق هذه الصفحة, ، يمكنك تجميع libgc (مكتبة Boehm-GC) مع

-DREDIRECT_MALLOC=GC_malloc -DIGNORE_FREE

الذي يجب أن اعتراض المكالمة إلى malloc في asprintf. NB: لم يحاول هذا.

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