下面給出的源代碼是一些更詳細的C源代碼的精簡版本,它解析輸入字符串以查看它們是否匹配預定義的模式。代碼嘗試解析輸入字符串(您可以假設它是一個有效的以空字符結尾的字符串)。如果 該字符串包含有效的無符號整數,則函數返回0,否則返回錯誤-1。無符號整數與正則表達式[0-9] + $匹配。代碼中可能的內存錯誤和可能的解決方案?
我試着運行valgrind命令來找出顯示以下輸出(我無法理解)的可能錯誤。
==15269==
==15269== Invalid read of size 1
==15269== at 0x400770: parse_exact (assign2b.c:23)
==15269== by 0x400957: xtz_parse_unsigned (assign2b.c:82)
==15269== by 0x400A26: test_parse_unsigned (assign2b.c:102)
==15269== by 0x400B06: main (assign2b.c:128)
==15269== Address 0x51f2045 is 0 bytes after a block of size 5 alloc'd
==15269== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15269== by 0x4EBAD81: strdup (strdup.c:43)
==15269== by 0x400AF1: main (assign2b.c:127)
==15269==
==15269== Invalid read of size 1
==15269== at 0x400770: parse_exact (assign2b.c:23)
==15269== by 0x400957: xtz_parse_unsigned (assign2b.c:82)
==15269== by 0x400A26: test_parse_unsigned (assign2b.c:102)
==15269== by 0x400B9B: main (assign2b.c:142)
==15269== Address 0x51f2135 is 0 bytes after a block of size 5 alloc'd
==15269== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15269== by 0x400B72: main (assign2b.c:140)
以下是代碼。請告訴代碼和可能的解決方案,以及如何同這些錯誤可以使用的valgrind
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define OK 9999
#define EOS '\0'
#define XT_SUCCESS 0
#define XT_FAIL -1
typedef int (*PARSE_FUNC)(const char *s, const char **endptr);
static int parse_exact(const char *s, const char **endptr, PARSE_FUNC pfunc)
{
const char *cp = s;
int c;
int state = 1;
while (state != XT_SUCCESS && state != XT_FAIL)
{
c = *cp++; // nextchar
switch(state)
{
case 1:
state = pfunc(--cp, endptr);
cp = *endptr;
if (state == XT_SUCCESS) state = 2;
else cp++; // on FAIL jump ahead to get undone on exit
break;
case 2:
if (EOS == c) state = OK;
else state = XT_FAIL;
break;
case OK:
state = XT_SUCCESS;
break;
default:
/* LOGIC ERROR */
assert(0==1);
break;
}
}
if (endptr)
*endptr = --cp;
return state;
}
static int base_unsigned(const char *s, const char **endptr)
{
const char *cp = s;
int c;
int state = 1;
while (state != XT_SUCCESS && state != XT_FAIL)
{
c = *cp++; // getnextchar
switch(state)
{
case 1:
if (isdigit(c)) state = 2;
else state = XT_FAIL;
break;
case 2:
if (isdigit(c)) state = 2;
else state = XT_SUCCESS;
break;
default:
/* LOGIC ERROR */
assert(0==1);
break;
}
}
if (endptr)
*endptr = --cp;
return state;
}
int xtz_parse_unsigned(const char *s, const char **endptr)
{
PARSE_FUNC pfunc = base_unsigned;
return parse_exact(s, endptr, pfunc);
}
void xt_pr_error(int status, const char *s, const char *endptr)
{
if (0 != status)
{
if (endptr[0])
printf("ERROR: '%c' at position %d is not allowed", *endptr, (endptr - s)+1);
else if ((endptr - s) > 0)
printf("ERROR: cannot end with '%c'", endptr[-1]);
else
printf("ERROR: value is empty");
}
}
void test_parse_unsigned(const char *s, int expected)
{
int status;
const char *endptr; // Ptr to first invalid character
status = xtz_parse_unsigned(s, &endptr);
printf("Test input='%s' status=%d ", s, status);
xt_pr_error(status, s, endptr);
if (status != expected)
printf(" NOT EXPECTED!\n");
else
printf(" (OK)\n");
}
int main(void)
{
char s1234[] = "1234";
char s12a4[] = "12a4";
char *ptr;
// Tests with string literals
test_parse_unsigned("1234", XT_SUCCESS);
test_parse_unsigned("12a4", XT_FAIL);
// Tests with static strings arrays
test_parse_unsigned(s1234, XT_SUCCESS);
test_parse_unsigned(s12a4, XT_FAIL);
// Tests using strdup()
ptr = strdup("1234");
test_parse_unsigned(ptr, XT_SUCCESS);
free(ptr);
ptr = strdup("123a");
test_parse_unsigned(ptr, XT_FAIL);
free(ptr);
ptr = strdup("1a34");
test_parse_unsigned(ptr, XT_FAIL);
free(ptr);
// Test using malloc and strcpy()
ptr = malloc(5);
strcpy(ptr, "1234");
test_parse_unsigned(ptr, XT_SUCCESS);
free(ptr);
return 0;
}
請指明'assign2b.c:23'是。 – timrau