【问题标题】:My Program Keeps Failing With - Error While Loading Shared Libraries我的程序一直失败 - 加载共享库时出错
【发布时间】:2015-01-12 14:41:27
【问题描述】:

我编写了一个程序 "run_coffee.c" 来实现 fork()exec() 系统调用。它从根本上调用 exec 来启动另一个通过 "coffee.c" 多次构建的进程 "coffee"。问题是我在 Windows 环境中的 cygwin64 上运行这个程序,它一直失败并出现以下错误 - **

加载共享库时出错:?: 无法打开共享对象 文件:没有这样的文件或目录

**

我还运行了 cygcheck 来查看是否满足依赖关系。这是输出 -

C:\cygwin64\home\Admin\run_coffee.exe C:\cygwin64\bin\cygwin1.dll

C:\Windows\system32\KERNEL32.dll

C:\Windows\system32\API-MS-Win-Core-RtlSupport-L1-1-0.dll

C:\Windows\system32\ntdll.dll C:\Windows\system32\KERNELBASE.dll

C:\Windows\system32\API-MS-Win-Core-ProcessThreads-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Heap-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Memory-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Handle-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Synch-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-File-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-IO-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-ThreadPool-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-LibraryLoader-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-NamedPipe-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Misc-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-SysInfo-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Localization-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-ProcessEnvironment-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-String-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Debug-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-ErrorHandling-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Fibers-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Util-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Core-Profile-L1-1-0.dll

C:\Windows\system32\API-MS-Win-Security-Base-L1-1-0.dll

没有出现错误或未满足的依赖项,所以我猜所有的依赖项都得到满足。那么是什么导致了这个问题呢?请帮忙。

这是两个程序 -

咖啡.c

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

int main(int argc, char *argv[])
{
    char  *w = getenv("EXTRA");
    if (!w)
        w = getenv("FOOD");
    if (!w)
        w = argv[argc-1];
    char *c = getenv("EXTRA");
    if (!c)
        c = argv[argc-1];
    printf("%s with %s\n", c, w);
    return 0;
}

run_coffee.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

struct food_options
{
    char *food;
    char *extra;
};

int main()
{
    int i;
    char **env;
    env[0] = (char*)malloc(sizeof(char) * 20);
    env[1] = (char*)malloc(sizeof(char) * 20);
    env[2] = (char*)malloc(sizeof(char) * 20);
    struct food_options *opts = (struct food_options *)malloc(sizeof(struct food_options) * 3);
    opts[0].food = "coffee";
    opts[0].extra = "donuts";
    opts[1].food = "fish";
    opts[1].extra = "chips";
    opts[2].food = "kabab";
    opts[2].extra = "parantha";



    for (i = 0; i < 3; i++)
    {
        pid_t pid = fork();
        if (pid == -1)
        {
            fprintf(stderr, "Cannot fork process. Fatal Error %s\n", strerror(errno));
            return 1;
        }

        else if (!pid)
        {
            sprintf(env[0], "FOOD=%s", opts[0].food);
            sprintf(env[1], "EXTRA=%s", opts[0].extra);
            env[2] = NULL;
            if (execle("coffee.exe","coffee.exe",NULL,env) == -1)
            {
                fprintf(stderr, "Cannot execute coffee.exe. Error %s\n", strerror(errno));
            }
        }
    }
    free(opts);
    free(env[0]);
    free(env[1]);
    free(env[2]);
    return 0;
}

【问题讨论】:

  • 你应该使用POSIX系统(如Linux)来玩fork;不要指望它会在 Windows 上被 Cygwin 忠实地模仿。
  • 我知道。但是 Cygwin 声称要在 windows 中创建一个类似 linux 的环境,不是吗?
  • 我相信邪恶在于细节。您可能无法完全在 Windows 上模拟 POSIX。所以学好 Linux,只有当你在 Linux 上有好的程序时,才会尝试痛苦地将它们移植到 Cygwin。
  • 公平点。那你建议我应该怎么做才能让它发挥作用。
  • 在您的笔记本电脑上安装 Linux。在 Linux 上使用 gcc -Wall -Wextra -g 编译。在 Linux 上使用 gdbstrace 进行调试。

标签: c windows gcc dll cygwin


【解决方案1】:

您的程序中有一个内存错误,可能导致未定义的行为:您将 env 声明为 char* 的数组,但您没有初始化 env。因此,env[0]、env[1] 和 env[2] 指向内存中的随机位置。当您执行 sprintf(env[0], ...) 和 sprintf(env[1], ...) 时,您正在将数据写入内存中的某个随机位置(env[0] 和 env[1] 指向的位置)到)。这可能导致几乎任何事情发生,包括修改库名称,使您无法加载它们。

【讨论】:

  • 我已经编辑了我的程序以消除内存错误。你想看看吗?
  • 还有一个问题:现在env是char**,所以需要先malloc数组env。您仍然可以将 env 声明为: char * env[3];只需更改声明,上述代码至少可以在 Linux 上为我工作(而您的代码在段错误之上)。通常,您应该使用 -Wall 选项编译代码,该选项会针对未定义的行为发出多种类型的警告(例如,它会捕获此错误)。
猜你喜欢
  • 1970-01-01
  • 2014-01-22
  • 2011-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多