在C中返回字符串时管理内存

时间:2014-08-17 15:48:33

标签: c string memory visual-studio-2013 return

我有一个CGI应用程序,我一直在Visual Studio Express 2013中编写,但是我遇到了一个场景,当传递给函数的字符串超过31个字节时程序失败。我会尝试自己调试它,但在Visual Studio Debugger中一切正常,它只在命令提示符中我看到错误。

我相信这是我分配(或未分配)内存的方式。我有一个函数,它接受一个字符串并返回解码后的字符串。

我已经把所有内容都删除到了那个函数和main,所以你可以看到两个案例,一个在CMD中工作,另一个在失败中。

这是文件:

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

/*
* Function: urlDecode
* Purpose:  Decodes a web-encoded URL
* Input:    const char* str - the URL to decode
* Output:   char* - the decoded URL
*/
char *urlDecode(const char *str) {
    int d = 0; /* whether or not the string is decoded */

    char *dStr = malloc(strlen(str) + 1);
    char *eStr = malloc(2); /* a hex code */

    strcpy(dStr, str);

    while (!d) {
        d = 1;
        int i; /* the counter for the string */
        int j = strlen(dStr);

        for (i = 0; i<j; ++i) {
            if (dStr[i] == '%') {
                if (dStr[i + 1] == 0)
                    return dStr;

                if (isxdigit(dStr[i + 1]) && isxdigit(dStr[i + 2])) {
                    d = 0;

                    //combine the next two numbers into one
                    eStr[0] = dStr[i + 1];
                    eStr[1] = dStr[i + 2];

                    //convert it to decimal
                    long int x = strtol(eStr, NULL, 16);

                    //remove the hex
                    memmove(&dStr[i], &dStr[i + 2], strlen(dStr) - 1);

                    dStr[i] = x;
                    j = j - 2;
                }
            }
        }
    }
    free(eStr);
    return dStr;
}

int main(void)
{
    //this one runs fine from command prompt
    char *test1 = "s=W3%20%3A%20SVC&action=stop";
    printf("%s\n", test1);
    char *decoded1 = urlDecode(test1);
    printf("%s\n", decoded1);
    free(decoded1); //and I can even free the memory

    //this one prints in command prompt, but the program crashes immediately after
    char *test2 = "service=W3%20%3A%20SVC&action=stop";
    printf("%s\n", test2);
    char *decoded2 = urlDecode(test2);
    printf("%s\n", decoded2);
    //when I comment this free out, it debugs fine in VS, but still fails in cmd
    //this is the reason I believe it's a memory error
    //free(decoded2); 

    system("PAUSE"); //so I can see what's happening

    return 0;
}

2 个答案:

答案 0 :(得分:3)

您无法空终止eStr,并且没有为其分配足够的内存:您需要三个字符,而不是两个字符。

由于eStr太短,请考虑将其作为堆栈变量,而不是在动态存储上分配它:

char eStr[] = "00";

这将分配足够的空间,并且不必在函数末尾free指针。

另一个问题是memmove:看起来您的索引已关闭。您可以修复它,但更容易完全避免memmove:而不是进行替换,使用str作为您的来源,dStr作为您的目的地:< / p>

char *urlDecode(const char *str) {
    int d = 0; /* whether or not the string is decoded */

    char *dStr = malloc(strlen(str) + 1);
    char *ret = dStr;
    char eStr[] = "00";

    strcpy(dStr, str);

    while (!d) {
        d = 1;
        int i; /* the counter for the string */
        int j = strlen(dStr);

        for (i = 0; i<j; ++i) {
            if (str[i] == '%') {
                if (str[i + 1] == 0) {
                    break;
                }
                if (isxdigit(str[i + 1]) && isxdigit(str[i + 2])) {
                    d = 0;

                    //combine the next two numbers into one
                    eStr[0] = str[i + 1];
                    eStr[1] = str[i + 2];

                    //convert it to decimal
                    long int x = strtol(eStr, NULL, 16);

                    *dStr++ = x;
                }
            } else {
                *dStr++ = str[i];
            }
        }
    }
    *dStr = 0;
    return ret;
}

Demo.

答案 1 :(得分:2)

应该是

char *eStr = calloc(3,1); /* a hex code */

memmove(&dStr[i+1], &dStr[i + 3], strlen(&dStr[i+3])+1 );