【问题标题】:Managing memory when returning string in C在 C 中返回字符串时管理内存
【发布时间】:2014-10-10 15:08:37
【问题描述】:

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

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

我已将所有内容简化为该函数和 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;
}

【问题讨论】:

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


    【解决方案1】:

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

    由于eStr 很短,考虑将其设为堆栈变量,而不是在动态存储中分配它:

    char eStr[] = "00";
    

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

    另一个问题是memmove:看起来您的索引已关闭。您可以修复它,但完全避免 memmove 会容易得多:与其原地替换,不如使用 str 作为源,dStr 作为目标:

    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.

    【讨论】:

    • 您对 eStr 的看法是对的,我会立即解决这个问题。不过,在 cmd 中运行代码仍然失败,我认为它与您链接到的演示中的 stderr 输出有关
    • @AbeFehr 啊,我没有注意到stderr。让我看看那里发生了什么。像这样的输出通常意味着您在分配给您的地址之前已经写入了地址。
    • 这是我的记忆,正如 BLUEPIXY 的回答所指出的那样。谢谢你们!
    【解决方案2】:

    应该是

    char *eStr = calloc(3,1); /* a hex code */
    
    memmove(&dStr[i+1], &dStr[i + 3], strlen(&dStr[i+3])+1 );
    

    【讨论】:

      猜你喜欢
      • 2010-10-11
      • 1970-01-01
      • 1970-01-01
      • 2020-09-21
      • 1970-01-01
      • 2011-10-22
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多