مشكلة مع RealLoc () في C. معلقة دائمًا ولكنها تجمع بشكل جيد
-
01-10-2019 - |
سؤال
أواجه بعض المشاكل مع برنامج يهدف إلى أن يكون مخزن المؤقت سلسلة ، وتحديداً هذه الوظيفة تهدف إلى إعادة تعيين المخزن المؤقت مع السلسلة CSTR. إذا كان CSTR فارغًا ، فيجب إعادة تعيين المحتوى إلى char فارغ ' 0'. إنه معلق دائمًا في المجموعة الثانية من RealLoc حيث يتم تغيير حجم محتويات buf-> ليس لدي أدنى فكرة عن سبب ذلك. أي مساعدة ستكون رائعة.
الهيكل:
typedef struct strbuf {
char *contents;
size_t length;
} StringBuffer;
يسمى من
strbuf_reset(sb, NULL)
فيما يلي وظيفة strbuf_reset التي تواجه المشكلة.
StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if(buf == NULL)
return NULL;
StringBuffer *tempBuf = NULL ;
if(cstr == NULL)
tempBuf = (StringBuffer*)realloc(buf,sizeof(StringBuffer) + sizeof(char));
else
tempBuf = (StringBuffer*)realloc(buf,sizeof(buf) + strlen(cstr)*sizeof(char));
if(tempBuf == NULL)
return NULL;
if(cstr == NULL)
tempBuf->contents = (char*)realloc(buf->contents,sizeof(char));
else
tempBuf->contents = (char*)realloc(buf->contents,(sizeof(buf->contents) + strlen(cstr)*sizeof(char) + 1));
if(tempBuf->contents == NULL){
free(tempBuf);
return NULL;
}
buf = tempBuf;
if(cstr == NULL)
buf->contents = '\0';
else
strcat(buf->contents,cstr);
buf->length = strlen(buf->contents);
return buf;
}
مع ما أعتقد أنه التغييرات المقترحة ...
StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if(buf == NULL)
return NULL;
StringBuffer *tempBuf = NULL ;
if(cstr == NULL)
tempBuf = (StringBuffer*)realloc(buf,sizeof(StringBuffer) + sizeof(char) + 10);
else
tempBuf = (StringBuffer*)realloc(buf,sizeof(buf) + strlen(cstr)*sizeof(char)+ 1);
if(tempBuf != NULL)
buf = tempBuf;
else
return NULL;
if(cstr == NULL)
tempBuf->contents = (StringBuffer*)realloc(buf->contents,sizeof(StringBuffer) + sizeof(char) + 10);
else
tempBuf->contents = (StringBuffer*)realloc(buf->contents,sizeof(buf) + strlen(cstr)*sizeof(char)+ 1);
if(tempBuf != NULL)
buf->contents = tempBuf->contents;
else
return NULL;
if(cstr == NULL)
buf->contents = '\0';
else
strcat(buf->contents,cstr);
buf->length = strlen(buf->contents);
return buf;
}
المحلول
نظرًا لأنك ستحصل على كتابة محتويات StringBuffer ، فإن استخدام RealLoc لا معنى له. لن يوفر لك أي تخصيص ذاكرة ، ولكن بدلاً من ذلك سيقوم بنسخ البيانات القديمة التي تنوي الكتابة فوقها على أي حال. استخدام malloc العادي ومرة.
مع هيكلك الأصلي
typedef struct strbuf {
char *contents;
size_t length;
} StringBuffer;
strbuf_reset يحدد buf إلى cstr. على النجاح يعود buf ، على الفشل لاغية.
StringBuffer *strbuf_reset(StringBuffer *buf, const char *cstr)
{
if (!buf) return NULL;
if (!cstr) cstr = "";
size_t len = strlen(cstr);
if (len > buf->length) {
char *new_contents = malloc(len + 1);
if (!new_contents) return NULL;
free(buf->contents);
buf->contents = new_contents;
}
memcpy(buf->contents, cstr, len + 1);
buf->length = len;
return buf;
}
نصائح أخرى
لا يبدو أنك تفهم ماذا realloc
يفعل.
الطريقة التي ينبغي أن تفكر في الأمر (على الأقل بقدر ما يذهب التكبير) ، هو أنه يخصص المخزن المؤقت الجديد ، ونسخ البيانات القديمة فيها ، وبعد ذلك يحرر المخزن المؤقت القديم.
المؤشر القديم إذن غير صالحة ويجب ألا يكون الأمر مفاجئًا إذا تعطلت عندما تحاول استخدامه مرة أخرى لاحقًا.
يجب عليك تعيين القيمة التي تم إرجاعها إلى المؤشر القديم على الفور ، لذلك لا يزال يشير إلى بيانات صالحة.
أنت تقوم بتخصيص مساحة إضافية للسلسلة في StringBuffer. لقد افترضت فقط أن محتويات buf-> من المفترض أن تشير إلى هذه المساحة المخصصة الإضافية. إذا لم يكن هذا صحيحًا فلماذا يتم تخصيص المساحة الإضافية في StringBuffer؟
إذا كانت محتويات BUF-> تشير بالفعل إلى الذاكرة التي تم تخصيصها لـ StringBuffer ، في محاولة لإعادة تخصيصها في وضع نظام الذاكرة في حالة تعطل/تعليق/فاسد ، لأنك ستقوم بإعادة تخصيص مؤشر لم يتم تخصيصه أبدًا.
بدلاً من محاولة إعادة محتويات BUF-> ، أعتقد أن الهيكل يجب أن يبدو:
struct StringBuffer {
size_t length;
char contents[1];
};
ثم بدلاً من محتويات إعادة تخصيص buf-> تقوم فقط بنسخ السلسلة إلى هناك ، ويعتني REALLOC لـ StringBuffer بكل الذاكرة.