与ASIO独立的段错误时,班单独的文件 [英] Segfault with asio standalone when classes in separate files

查看:325
本文介绍了与ASIO独立的段错误时,班单独的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是最小的一个例子,因为我可以得到的。它需要在独立的文件,这似乎是什么原因导致分段错误。

The below is as minimal of an example as I can get. It does need to be in separate files as that seems to be what causes the segmentation fault error.

我使用称为Mingw X32 4.8.1与短耳独立1.10.6。我也与TDM GCC 4.7.1和M​​inGW 4.8.1 x64的测试。所有这些在Windows下产生相同的段错误。有没有这样的问题,在Linux下使用GCC的最新版本。

I'm using Mingw x32 4.8.1 with Asio standalone 1.10.6 . I've also tested with TDM GCC 4.7.1 and Mingw x64 4.8.1. All of these under Windows produce the same segfault. There's no such issue under Linux with the latest version of GCC.

编辑:我刚刚完成测试MingW平台上-W64 5.2.0(MinGW的,构建它的版本)。同样的问题。

edit: I've just finished testing on Mingw-w64 5.2.0 (the Mingw-Builds build of it). Same problem.

我也测试了TDM GCC 4.8.1新的虚拟机上编译这一点,并得到相同的段错误。编辑:我现在也测试了一个完全不同的机器上TDM GCC 4.8.1

I've also tested compiling this with TDM GCC 4.8.1 on a fresh virtual machine and get the same segfault. I've also now tested on a completely different machine with TDM GCC 4.8.1

在我使用所有的情况下 -std = C ++ 11 -g -Wall 。我也编译了 -g ,并有相同的结果。我需要的C ++ 11的标志,因为我不希望在提升的依赖,只是ASIO。

In all cases I'm using -std=c++11, -g and -Wall. I've also compiled with -g and have the same result. I need the C++11 flag because I don't want a dependency on boost, just asio.

通过在一个单一的以下code 的main.cpp 文件,不会有问题,程序似乎运行正常。但是,如果我把每一个类到它自己的 *。HPP *。CPP 文件,我得到了段错误在服务器类的构造函数。

With the following code in a single main.cpp file there are not problems and the program seems to run as expected. However, if I put each class into it's own *.hpp and *.cpp file, I get a segfault in the Server classes constructor.

我再回去,并把所有的东西放回的main.cpp ,开始由一个移动每个类之一。该段错误开始最后一节课后存在的,客户端放在它自己的文件。

I further went back and put everything back into main.cpp and started moving each class one by one. The segfault begins occuring after the final class, Client is put in it's own files.

另外,因为我把所有的类合并成一个文件,并移动它们等等,我确信,任何未所需的目标文件没有链接到我的.exe文件。

In addition, as I was putting all the classes into one file and moving them etc, I made sure that any un-needed object files weren't linked to my .exe.

这code开始大量大,但它的范围缩小到了这一点。

This code started a lot larger but it's narrowed down to this.

Server.hpp

#ifndef SERVER_HPP_INCLUDED
#define SERVER_HPP_INCLUDED

#include <string>
#include <memory>

#define ASIO_STANDALONE
#include <asio.hpp>
using namespace asio::ip;

namespace network
{
    class Server
    {
    public:

        Server(asio::io_service& ioService, uint16_t port);

    private:

        tcp::acceptor m_acceptor;
    };
}

#endif // SERVER_HPP_INCLUDED

Server.cpp

#include "Server.hpp"
using namespace network;

#include <iostream>

Server::Server(asio::io_service& ioService, uint16_t port)
: m_acceptor(ioService, tcp::endpoint(tcp::v4(),port))
{
}

Client.hpp

#ifndef CLIENT_HPP_INCLUDED
#define CLIENT_HPP_INCLUDED

#include <vector>

#define ASIO_STANDALONE
#include <asio.hpp>
using namespace asio::ip;

namespace network
{
    class Client
    {
    public:

        Client(asio::io_service& ioService);

    private:

        asio::steady_timer m_timer;
    };
}

#endif // CLIENT_HPP_INCLUDED

Client.cpp

#include "Client.hpp"
using namespace network;

#include <iostream>

Client::Client(asio::io_service& ioService)
: m_timer(ioService)
{
}

的main.cpp

#include <iostream>

#define ASIO_STANDALONE
#include <asio.hpp>
using namespace asio::ip;

#include "Server.hpp"

int main()
{
    try
    {
        uint16_t peerRequestPort = 63000;

        asio::io_service io_service;

        network::Server server(io_service,peerRequestPort);
    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

下面是从GDB调用堆栈:

Here's the callstack from GDB:

#0 00406729 asio::detail::service_registry::keys_match(key1=..., key2=...) (F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/detail/impl/service_registry.ipp:89)
#1 ??   0x0040696e in asio::detail::service_registry::do_use_service (this=0x5d2f10, key=..., factory=0x406b44 <asio::detail::service_registry::create<asio::socket_acceptor_service<asio::ip::tcp> >(asio::io_service&)>) (F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/detail/impl/service_registry.ipp:113)
#2 004068B6 asio::detail::service_registry::use_service<asio::socket_acceptor_service<asio::ip::tcp> >(this=0x5d2f10) (F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/detail/impl/service_registry.hpp:47)
#3 00403857 asio::use_service<asio::socket_acceptor_service<asio::ip::tcp> >(ios=...) (F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/impl/io_service.hpp:32)
#4 004039B3 asio::basic_io_object<asio::socket_acceptor_service<asio::ip::tcp>, true>::basic_io_object(this=0x28fe48, io_service=...) (F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/basic_io_object.hpp:182)
#5 00403B29 asio::basic_socket_acceptor<asio::ip::tcp, asio::socket_acceptor_service<asio::ip::tcp> >::basic_socket_acceptor(this=0x28fe48, io_service=..., endpoint=..., reuse_addr=true) (F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/basic_socket_acceptor.hpp:137)
#6 00401D3B network::Server::Server(this=0x28fe48, ioService=..., port=63000) (F:\GameDev\Dischan\Tests\Server.cpp:7)
#7 004018F1 main() (F:\GameDev\Dischan\Tests\main.cpp:17)

最后这里是从内存DR的输出:

And finally here's the output from Dr Memory:

Dr. Memory version 1.8.0 build 8 built on Sep  9 2014 16:27:02
Dr. Memory results for pid 5296: "tests.exe"
Application cmdline: "tests.exe"
Recorded 108 suppression(s) from default C:\Program Files (x86)\Dr. Memory\bin\suppress-default.txt

Error #1: UNADDRESSABLE ACCESS: reading 0x00000007-0x0000000b 4 byte(s)
# 0 asio::detail::service_registry::keys_match                         [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/detail/impl/service_registry.ipp:89]
# 1 asio::detail::service_registry::do_use_service                     [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/detail/impl/service_registry.ipp:113]
# 2 asio::detail::service_registry::use_service<>                      [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/detail/impl/service_registry.hpp:47]
# 3 asio::use_service<>                                                [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/impl/io_service.hpp:32]
# 4 asio::basic_io_object<>::basic_io_object                           [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/basic_io_object.hpp:182]
# 5 asio::basic_socket_acceptor<>::basic_socket_acceptor               [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/basic_socket_acceptor.hpp:137]
# 6 network::Server::Server                                            [F:/GameDev/Dischan/Tests/Server.cpp:7]
# 7 main                                                               [F:/GameDev/Dischan/Tests/main.cpp:17]
Note: @0:00:00.780 in thread 7464
Note: instruction: mov    0x04(%eax) -> %eax

Error #2: LEAK 36 direct bytes 0x02530860-0x02530884 + 124 indirect bytes
# 0 replace_operator_new                       [d:\drmemory_package\common\alloc_replace.c:2609]
# 1 asio::io_service::io_service               [F:/GameDev/asio-1.10.6/asio-1.10.6/include/asio/impl/io_service.ipp:39]
# 2 main                                       [F:/GameDev/Dischan/Tests/main.cpp:15]

===========================================================================
FINAL SUMMARY:

DUPLICATE ERROR COUNTS:

SUPPRESSIONS USED:

ERRORS FOUND:
      1 unique,     1 total unaddressable access(es)
      0 unique,     0 total uninitialized access(es)
      0 unique,     0 total invalid heap argument(s)
      0 unique,     0 total GDI usage error(s)
      0 unique,     0 total handle leak(s)
      0 unique,     0 total warning(s)
      1 unique,     1 total,    160 byte(s) of leak(s)
      0 unique,     0 total,      0 byte(s) of possible leak(s)
ERRORS IGNORED:
     14 potential error(s) (suspected false positives)
         (details: C:\Users\User\AppData\Roaming\Dr. Memory\DrMemory-tests.exe.5296.000\potential_errors.txt)
     12 potential leak(s) (suspected false positives)
         (details: C:\Users\User\AppData\Roaming\Dr. Memory\DrMemory-tests.exe.5296.000\potential_errors.txt)
     24 unique,    24 total,   2549 byte(s) of still-reachable allocation(s)
         (re-run with "-show_reachable" for details)
Details: C:\Users\User\AppData\Roaming\Dr. Memory\DrMemory-tests.exe.5296.000\results.txt

我只是不明白为什么我得到段错误。即使注释掉一切仍出现有意义code后。

I just cannot see why I'm getting a segfault. Even after commenting out all of the meaningful code it still occurs.

修改

我已经编辑了code以上,表明仅仅是服务器构造似乎引起一个问题,每个文件的内容。 (我又确保只有这些目标文件编译和链接)。

I've edited the code above to show that just the Server constructor appears to cause an issue and the contents of each file. (I've again ensured that only these object files are compiled and linked).

编辑2

我的TDM GCC 4.7.1测试这一点,称为Mingw构建64 4.8.1和MinGW构建X32 4.8.1。同样的结果对于他们。

I've tested this with the TDM GCC 4.7.1, Mingw Builds x64 4.8.1 and Mingw Builds x32 4.8.1. Same result for all of them.

编辑3

我已经进一步降低了code一路下滑。现在,在客户端,如果我删除那些需要 ASIO 对象ASIO :: io_service对象和放大器; 来建造,那么有没有段错误。但是,任何到目前为止,我已经试过了 ASIO 类型都产生相同的段错误。这是不是在服务器类的实例,它有一个 ASIO ::受体的一个问题。在遥远的事情是,有没有客户端创建的,那么,为什么它会影响程序和产生一个段错误服务器的构造是奇怪的。

I've further reduced the code way down. Now, in Client, if I remove any asio objects that require an asio::io_service& to be constructed, then there is no segfault. But any of the asio types I've tried so far have all produced the same segfault. This isn't a problem in the Server class for instance, which has an asio::acceptor. The far out thing is that there is no instance of Client created, so why it affects the program and produces a segfault in Servers constructor is weird.

修改4

现在我已经完全删除 Server.hpp Server.cpp ,并已更新的main.cpp 来的:

I've now completely removed Server.hpp and Server.cpp and have updated main.cpp to this:

的main.cpp

#include <iostream>

#define ASIO_STANDALONE
#include <asio.hpp>
using namespace asio::ip;

int main()
{
    try
    {
        uint16_t peerRequestPort = 63000;

        asio::io_service io_service;

        auto protocol = tcp::v4();
        tcp::endpoint endpoint(protocol,peerRequestPort);
        tcp::acceptor m_acceptor(io_service, endpoint);

    }
    catch(std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

我仍然得到段错误和调用堆栈反映了缺乏服务器构造。该段错误仍然是在同一个地方。 DrMemory结果看起来差不多也是如此。

I still get the segfault and the callstack reflects the lack of Server constructor. The segfault is still in the same place. DrMemory results look about the same as well.

以前一样,如果我不链接客户端目标文件我没有问题。

Same as before, if I don't link the Client object file I have no issue.

修改5

根据要求,这里是从code :: Blocks的

As requested, here is the build log from Code::Blocks

g++.exe -std=c++11 -Wall -D_WIN32_WINNT=0x0501 -g -I..\..\asio-1.10.6\asio-1.10.6\include -c F:\GameDev\Dischan\Tests\Client.cpp -o obj\Debug\Client.o
g++.exe -std=c++11 -Wall -D_WIN32_WINNT=0x0501 -g -I..\..\asio-1.10.6\asio-1.10.6\include -c F:\GameDev\Dischan\Tests\main.cpp -o obj\Debug\main.o
g++.exe  -o Build\Debug\Windows\Tests.exe obj\Debug\Client.o obj\Debug\main.o   -lws2_32 -lwsock32
Output file is Build\Debug\Windows\Tests.exe with size 723.02 KB
Process terminated with status 0 (0 minute(s), 3 second(s))
0 error(s), 0 warning(s) (0 minute(s), 3 second(s))


修改6

我现在开始到外面去我的能力,但我已经成功地跟踪了一些问题(我学习一些新的东西这是很酷)。

I'm starting to go outside of my abilities now but I've managed to track down some of the problem (and I'm learning some new stuff which is cool).

看来,当一个对象,它需要一个 ASIO :: io_service对象和放大器; 创建,它增加了服务的 io_service对象。这些都是在所有 io_service对象实例静态的。这样,该服务请求时,有该被重复,通过它似乎是已创建的服务的链接列表的循环。如果所请求的服务并没有已经被创建;它的,那么创建。

It appears that when an object which requires an asio::io_service& is created, it adds "services" to the io_service. These are static across all io_service instances. So, when the service request is made, there's a loop that is iterated through which appears to be a linked list of already created services. If the requested service hasn't already been created; it's then created.

此信息是从参考 io_service对象 和看 service_registry.ipp (行111)。

This info is from the reference for io_service and from looking at service_registry.ipp (line 111).

这是内部一起通话service_registry :: do_use_service 完成。在 service_registry 有一个名为成员 first_service _ 键入 ASIO :: io_service对象::服务* 。这第一个服务应该有一个名为成员接下来_ 这是我所提到的链表的一部分。

This is done internally with a call to service_registry::do_use_service. The service_registry has a member named first_service_ of type asio::io_service::service*. This first service should have a member named next_ which is the linked list part I mentioned.

在第一次调用到 service_registry :: do_use_service 时(当 ASIO ::受体构造)但是, first_service _ 成员都有为0xffffffff 的值这显然是不正确的。所以我相信这就是段错误的根源。

At the time of the first call to service_registry::do_use_service (when the asio::acceptor is constructed) however, the first_service_ member has a value of 0xffffffff which is obviously not right. So I believe that's the root of the segfault.

为什么此成员值为为0xffffffff 我是无法理解。这是我的理解是,只有老/古怪的机器保留了这个地址指针...但我承认我可能是遥远。

Why this member has the value 0xffffffff is beyond me. It was my understanding that only old/quirky machines reserved this address for null pointers... but I concede I could be way off.

我也只是快速地检查,通过这样做:

I did just quickly check that by doing this:

int* p = nullptr;
if(p)
    std::cout << "something" << std::endl;

和设置一个断点阅读价值。为 P 的值是为0x0 ,而不是为0xffffffff

and set a breakpoint to read the value. The value for p is 0x0, not 0xffffffff.

所以,我设置的构造一个断点 service_registry ASIO /细节/ IMPL / service_registry.hpp )和析构函数(如果它被显式调用的地方),并在三种方法 do_has_service do_use_service do_add_service 。我的想法是尝试和跟踪在什么点 first_service _ 得到了错误的值。

So, I set a breakpoint on the constructor for service_registry (asio/detail/impl/service_registry.hpp) and on the destructor (in case it was explicitly called somewhere) and on the three methods do_has_service, do_use_service and do_add_service. My thought was to try and track at what point first_service_ gets the bad value.

我有没有运气。这些都是这有可能改变 first_service _ 的价值的唯一场所。

I've had no luck. These are the only places which could possibly alter the value of first_service_.

我想借此意味着事情已经损坏堆栈,改变了地址 first_service _ 。但是,我只是一个业余爱好者...

I take this to mean that something has corrupted the stack and changed the address for first_service_. But, I'm only a hobbyist...

我没有检查的地址这个指针的构造是一样用于 do_use_service ,以确保两个实例没有创建或类似的东西。

I did check that the address of the this pointer for the constructor was the same as the one used for the invocation of the do_use_service to make sure that two instances weren't created or something like that.

修改7

好了,现在我已经发现,如果我与编译 ASIO_DISABLE_THREADS 我不再得到段错误!

Okay, so I've now found that if I compile with the ASIO_DISABLE_THREADS I no longer get a segfault!

但是,这会导致抛出异常,因为我试图使用线程即使我禁用它们。我采取意味着我将限于同步调用,也没有异步调用。 (即什么是使用ASIO点?)

But, this results in an exception being thrown because I'm attempting to use threads even though I've disabled them. Which I take to mean that I would be restricted to synchronous calls and no async calls. (i.e., what's the point of using asio?)

材料不说该 ASIO_DISABLE_THREADS

明确禁止短耳的线程支持,独立与否升压支持多线程。

Explicitly disables Asio's threading support, independent of whether or not Boost supports threads.

所以我把它意味着这个ASIO定义使用,无论升压或不停止线;这是有道理的。

So I take it to mean that this define stops asio from using threads regardless of boost or not; which makes sense.

为什么线程会导致一个问题,我不知道。我并不热衷于钻研那么远。

Why threading would cause a problem, I don't know. I'm not keen on delving that far.

我放弃ASIO。通过code和文档寻找之后,它似乎已被记与提升开发更因此比作为一个独立的库。显然是为了在那里你需要使用升压比C ++ 11,我只是不小心做点。

I give up on asio. After looking through the code and documentation, it appears to have been developed with boost in mind more-so than as a standalone library. Apparently to the point where you need to use Boost over C++11, which I just don't care to do.

最佳C / C ++网络库看起来像有很多替代品。

Best C/C++ Network Library looks like there's lots of alternatives.

说实话,经营自己的同步套接字调用在我自己的线程听起来像一个更好的主意,考虑到我会得到控制。至少直到ASIO进入标准库,并称为Mingw-W64实现。

To be honest, running my own synchronous socket calls in my own thread sounds like a better idea considering the control I'll gain. At least until asio enters the Standard Library and is implemented in Mingw-w64.

考虑到ASIO看起来像一个总理候选人是在标准库,或至少它的味道,它可能是一个好主意,坚持下去。

Considering that asio looks like a prime candidate to be in the standard library, or at least it's flavour, it's probably a good idea to stick with it.

推荐答案

我觉得分段故障发生时,因为不匹配 Server.hpp之间ASIO类型定义 Client.hpp 。字符串&GT; &LT;内存&GT; &LT集定义这只能发生C>或&LT;矢量方式&gt;

I think the segmentation fault occurs because of mismatching asio type definitions between Server.hpp and Client.hpp. In your case, this could only happen if boost changes typedefs depending on defines set by <string>, <memory> or <vector>.

我的建议是尝试之一:


  1. 包括服务器/ Client.hpp和mai​​n.cpp中以同样的标题包括前asio.hpp:

  1. Include the same headers in both Server/Client.hpp and main.cpp before including asio.hpp:

#include <string>
#include <memory>
#include <vector>

#define ASIO_STANDALONE
#include <asio.hpp>


  • 或者干脆包括asio.hpp之前的任何其他包含头文件和删除的main.cpp中包含。

  • Or simply include asio.hpp before any other include in your header files and remove the include from main.cpp.

    这篇关于与ASIO独立的段错误时,班单独的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆