【问题标题】:Losing data when passing const char* to function将 const char* 传递给函数时丢失数据
【发布时间】:2016-05-31 05:36:56
【问题描述】:

这几天我一直在用一些 c 代码遇到问题,我到处寻找,但我不知道如何解决它,这让我发疯了!基本上发生的情况是函数_getfile()argv[1] 获取相对/绝对文件路径(假设它可用)并检查是否存在绝对文件路径以及文件是否可以打开和读取。然后该函数将该文件路径返回给 main 并将其存储为 const char*。到这里为止,一切正常。没有数据丢失或问题。但是一旦我将filepath 传递给任何其他函数,我的程序就会开始做一些疯狂的事情。 filepath 要么变成了一堆 \n 字符,要么只是丢失了一部分。 代码如下:

#include <limits.h> //PATH_MAX
#include <unistd.h> //access()
#include <stdio.h>
#include <stdlib.h>

const char* _getfile(int argcount, const char ** argvars) {
    //Check if filepath has been given as console parameter
    if (argcount == 1) {
        exit(EXIT_FAILURE);
    }

    //Get absolute path of given filepath
    const char* relpath = argvars[1];
    char buffer[PATH_MAX + 1];
    const char* abspath = realpath(relpath, buffer);

    //Check if an absolute path could be found
    if (abspath) {
        printf("Source at '%s'.\n", abspath);
    } else {
        printf("No absolute filepath could be found for '%s'.\n", relpath);
        exit(EXIT_FAILURE);
    }

    //Check if file exists
    if(access(abspath, F_OK) != -1) {
        //Check file for read permissions
        if (access(abspath, R_OK) != -1) {
            return abspath;
        } else {
            printf("'%s' couldn't be accessed as it lacks read permissions.\n", abspath);
            exit(EXIT_FAILURE);
        }
    } else {
        printf("'%s' doesn't exist.\n", abspath);
        exit(EXIT_FAILURE);
    }
}

void _readfile(const char* filename) {
    //'filename' has now been changed!
    FILE* file = NULL;
    file = fopen(filename, "r");
    /*
    Read/print file contents etc.
    ...
    */

int main(int argc, const char** argv) {
    const char* filepath = _getfile(argc, argv);
    _readfile(filepath);
    return 0;

假设我在控制台中将"/Users/Token/Desktop/Test.txt" 作为参数传递。当绝对文件路径返回到 main 时,仍然是 "/Users/Token/Desktop/Test.txt",一切都很好。当我将它传递给_readfile() 时,在函数内部,文件路径现在类似于"\n\n\n\n\n\n...""/Users/To",而其余部分则丢失了。对我来说,这看起来像是内存泄漏,但我找不到我做错了什么。上次我检查调试器时,buffer 似乎在我的机器上保存了 1025 个字符,所以这不是问题。我认为这并不重要,但我在 OS X El Capitan 10.11.13 上使用 XCode。提前感谢所有帮助!

【问题讨论】:

    标签: c function memory-leaks char constants


    【解决方案1】:

    您正试图返回一个本地指针。这永远不会起作用,因为当函数超出范围时,所有局部变量都会被销毁。所以返回值会有你看到的垃圾。

    您可以做以下两件事之一:

    1. 为接受返回值的函数添加一个参数。
    2. 在堆中定义返回值。 (这是一种不好的方法,因为一般来说,调用代码负责分配和释放堆内存。如果你在这个函数中分配内存,然后在外部释放它,它只是糟糕的编程:))

    【讨论】:

      【解决方案2】:

      您使用buffer 调用realpath,它是您的_getfile 函数中本地分配的变量。当您从函数返回时,它会被销毁并且不再有效。因此,您会在这里得到奇怪的值。使用NULL 作为realpath 调用的第二个参数,因此您将获得指向新分配缓冲区的指针。使用后别忘了free它。

      【讨论】:

        【解决方案3】:

        realpath 解析传递给它的字符串并将输出存储在作为第二个参数传递的缓冲区中

        char buffer[PATH_MAX + 1];
        const char* abspath = realpath(relpath, buffer);
        //                                       ^^^
        //                                in your case here
        

        这是代码中的局部变量。作为一个放入堆栈的数组,一旦你的函数返回就尝试访问它是非法的,并且它发生在调用者甚至触及希望返回但消失的东西之前。

        解决方案:

        将结果字符串的预分配缓冲区传递到_getfile:

        const char *
        _getfile(int argcount, const char ** argvars, char* buf)
        {
            const char* relpath, *abspath;
        
            relpath = argvars[1];
            abspath = realpath(relpath, buffer);
            if (abspath != NULL)
            {
                // OK
                return abspath;
            } else {
                // handle
            }
        

        【讨论】:

        • 现在完美运行。我想知道为什么我不能更早地掌握这个概念。感谢您提供信息丰富的回复,真的解决了问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-20
        • 1970-01-01
        相关资源
        最近更新 更多