【问题标题】:Segmentation fault in accept system call接受系统调用中的分段错误
【发布时间】:2016-07-20 11:11:15
【问题描述】:

我将以下代码用作接受传入套接字连接的服务器的主循环。

此时宏 OperationMode 被定义为 1,因此它将执行 pthread 逻辑。

for (hit = 1 ;; hit++) {
        printf("Got here\n\n");

        length = sizeof(cli_addr);

        /* block waiting for clients */
        socketfd = accept(listenfd, (struct sockaddr *) &cli_addr, &length);

        if (socketfd < 0)
                printf("ERROR system call - accept error\n");
        else
        {
                printf("Testing\n\n\n");
                #ifdef OperationMode
                        pthread_t thread_id;
                        if(pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL))
                        {
                                perror("could not create thread");
                                return 1;
                        }
                #else
                        pid = fork();
                        if(pid==0)
                        {
                                ftp(socketfd, hit);
                        }
                        else
                        {
                                close(socketfd);
                                kill(pid, SIGCHLD);
                        }
                #endif
        }
}

我能够为第一个传入的套接字连接创建一个线程,但是一旦我遍历循环,我就会在该行中遇到分段错误错误

socketfd = accept(listened, (struct sockaddr *) &cli_addr, &length);

我的attendFTP函数有以下代码

void *attendFTP(int fd, int hit)
{
    ftp(fd, hit);
    return NULL;
}

这非常适合 fork 实现。如何修复分段错误错误?

【问题讨论】:

  • 除非attendFTP() 是一个返回指向函数的指针的函数,否则您将错误地使用pthread_create()
  • @EOF 我已经添加了我的attendFTP() 函数。但我相信我使用正确
  • 您没有正确使用它。原型是int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);。如果您希望线程执行的函数需要多个参数,您可能需要传递一个指向 struct 的指针。

标签: c sockets pthreads posix ansi


【解决方案1】:
pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL);

此代码使用给定参数将调用结果传递给attendFTP() - 此结果始终为 NULL。

所以 pthread_create 试图在 NULL 地址处启动一个函数,并且相应地失败了。

如果您使用-pedantic 参数运行编译器,编译器会告诉您您的操作是错误的。如果没有-pedantic,gcc 允许一些“扩展”,这可能会隐藏错误。顺便说一句,这就是为什么-pedantic 在我看来是必须的。

你真正想要的是将一些参数传递给你的线程函数。不幸的是,它在 C pthreads 中确实很复杂,并且需要您分配和取消分配上述struct。像这样的:

struct args {
    int fd;
    int hit;
};
...
pthread_t thread_id;
struct args* args = malloc(sizeof(struct args));
args->fd = socketfd;
args->hit = hit;
if(pthread_create(&thread_id, NULL, attendFTP, args))
....

void* attendFTP(void* vargs)
{
    struct args* args = vargs;
    ftp(args->fd, args->hit);
    free(args);
    return NULL;
}

【讨论】:

  • 但是循环的第一次迭代执行成功,不应该失败吗?
  • @rafaelcpalmeida,不,它没有。但是由于您正在调用attendFTP,因此您基本上是首先在同一个线程中执行它(没有任何多线程)并看到一些结果。然后创建 pthread 并使应用程序崩溃。
  • 所以第一次调用不是真正的多线程?如何在attendFTP 函数中传递参数?你能分享一些例子吗?编辑:正如EOF所说,我设法使用带有参数的结构使其工作。
  • @rafaelcpalmeida,提供了一些代码。我不确定您所做的是否正确 - 如果您没有动态分配参数结构,那么您做错了。
  • 一切正常,谢尔盖。我也学过 -pedantic,我不知道!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多