在构造结构时会发生这种情况,我的代码: 此行http://wklej.org/hash/c42680a7f9d/txt/:http://wklej.org/hash/5fefcecc371/txt/回溯:http://wklej.org/id/451070/txt/ 任何帮助都是适当的 对不起,我没有在这里复制代码,所以我把它发布在任何其他网站上;(
答案 0 :(得分:2)
使用调试器并获得堆栈跟踪。
问题几乎可以肯定是将错误的C字符串传递给std :: string构造函数。也许指针无效或C字符串没有终止,构造函数读入受保护的内存。
但是如果没有更多信息,我无法分辨出错误是什么。调试器应该立即指出它。
此外,您的Socket
包含指针,但只定义构造函数和析构函数。您还需要一个复制构造函数和赋值运算符。如果不应该发生这两个操作,那么将它们定义为private
而没有实现。
另外,我从你的回溯中看到,这是GCC的旧版本。这个版本可能没有使std :: string在多线程程序中安全使用的修复程序。我不知道什么时候修复了,但libstdc ++库的一些旧版本没有锁定字符串上的引用计数,并且当不同的线程释放字符串内存同时也写入它时可能会崩溃。
答案 1 :(得分:2)
我已将您的代码放在此处,以便能够对其进行编辑:
#ifdef _WIN32
#define _WIN32_WINNT 0x0501
#endif
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <sstream>
#include <string>
#ifdef assert
#undef assert
#endif
#define assert(x)\
if (!x) { \
std::clog << "[Error - __FUNCTION__] Asseration to: " << #x << " failed. line: " << __LINE__ << ", file: " << __FILE__ << "." << std::endl;\
std::exit(100);\
}
template<typename _Tp>
inline std::string toString(_Tp __p)
{
std::stringstream ss;
ss << __p;
std::string ret;
ss >> ret;
return ret;
}
struct Proxy;
typedef std::vector<Proxy*> ProxyVec;
struct Proxy
{
std::string name;
uint32_t port;
};
ProxyVec loadProxies(const std::string& fileName)
{
std::FILE *f = fopen(fileName.c_str(), "r");
if (!f) {
std::clog << "[Error - loadProxies] Cannot open: " << fileName << "." << std::endl;
delete f;
f = NULL;
return ProxyVec();
}
char buffer[1024];
ProxyVec ret;
int32_t __n = 0;
while (fgets(buffer, sizeof(buffer), f)) {
++__n;
std::string str(buffer);
if (str.find("\n") != std::string::npos)
str = str.substr(0, str.length()-1);
if (str.find("\r") != std::string::npos)
str = str.substr(0, str.length()-1);
size_t sep = str.rfind(":");
if (sep == std::string::npos) {
std::clog << "[Error - loadProxies] Cannot load proxy #" << __n << "." << std::endl;
continue;
}
std::string hostname = str.substr(0, sep);
uint32_t port = static_cast<uint32_t>(std::atoi(str.substr(sep+1, str.length()-sep).c_str()));
std::clog << "Loading proxy: " << hostname << ":" << port << "." << std::endl;
Proxy proxy;
proxy.name = hostname;
proxy.port = port;
ret.push_back(&proxy);
}
std::clog << "Loaded: " << __n << " proxies." << std::endl;
return ret;
}
class Socket
{
public:
Socket(boost::asio::io_service& service, const std::string& host,
const std::string& port, const std::string& targetHost, const std::string& targetPort);
~Socket();
void write(const std::string& message);
std::string receivedData() const;
bool connected() const;
void receive();
void handle();
private:
struct SocketData
{
SocketData(boost::asio::io_service& service, const std::string& _host, const std::string& _port,
const std::string& _targetHost, const std::string& _targetPort):
socket(service),
write(service),
read(service),
resolver(service),
buffers(),
host(_host),
port(_port),
targetHost(_targetHost),
targetPort(_targetPort),
connected(false)
{
}
boost::asio::ip::tcp::socket socket;
boost::asio::io_service::strand write, read;
boost::asio::ip::tcp::resolver resolver;
boost::array<char, 1024> buffers;
std::string host, port;
std::string targetHost, targetPort;
bool connected;
};
// FIXME: Use shared_ptr instead.
SocketData* d;
protected:
//handle resolve func
void handle_resolve(const boost::system::error_code&,
boost::asio::ip::tcp::resolver::iterator);
//handle connection func
void handle_connect(const boost::system::error_code&,
boost::asio::ip::tcp::resolver::iterator);
//handle write func
void handle_write(const boost::system::error_code&, size_t);
//handle read func
void handle_read(const boost::system::error_code&, size_t);
private:
void connectionThread();
};
Socket::Socket(boost::asio::io_service& service, const std::string& host, const std::string& port,
const std::string& targetHost, const std::string& targetPort)
: d(new SocketData(service, host, port, targetHost, targetPort))
{
boost::thread thread(boost::bind(&Socket::connectionThread, this));
// FIXME: This function is blocking. The constructur will never exit.
// Use thread_group.join_all() as last line in main() instead.
thread.join();
}
Socket::~Socket()
{
d->socket.close();
delete d;
d = NULL;
}
void Socket::connectionThread()
{
if (!d)
return;
if (d->connected)
return;
boost::asio::ip::tcp::resolver::query query(d->host, d->port);
d->resolver.async_resolve(query,
boost::bind(&Socket::handle_resolve, this,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
}
void Socket::handle_resolve(const boost::system::error_code& e,
boost::asio::ip::tcp::resolver::iterator ep_iter)
{
if (!e) {
boost::asio::ip::tcp::endpoint iter = *ep_iter;
d->socket.async_connect(iter,
boost::bind(&Socket::handle_connect, this,
boost::asio::placeholders::error, ++ep_iter));
} else {
std::clog << "[Error - Socket::handle_resolve] " << e.message() << "." << std::endl;
}
}
void Socket::handle_connect(const boost::system::error_code& e,
boost::asio::ip::tcp::resolver::iterator ep_iter)
{
if (!e) {
std::cout << "[Notice - Socket::handle_connect] Connected to host." << std::endl;
d->connected = true;
write("CONNECT " + d->targetHost + ":" + d->targetPort + " HTTP/1.1\r\n\r\n");
receive();
} else if (ep_iter != boost::asio::ip::tcp::resolver::iterator()) {
d->socket.close();
boost::asio::ip::tcp::endpoint ep = *ep_iter;
d->socket.async_connect(ep,
boost::bind(&Socket::handle_connect, this,
boost::asio::placeholders::error, ++ep_iter));
} else {
std::clog << "[Error - Server::handle_connect] " << e.message() << "." << std::endl;
}
}
void Socket::handle_write(const boost::system::error_code& e,
size_t bytes)
{
assert(!e || bytes < 0);
}
void Socket::handle_read(const boost::system::error_code& e,
size_t bytes)
{
assert(!e || bytes < 0);
std::cout << receivedData() << std::endl;
receive();
}
void Socket::write(const std::string& message)
{
boost::asio::async_write(d->socket, boost::asio::buffer(message),
d->write.wrap(
boost::bind(&Socket::handle_write, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
std::string Socket::receivedData() const
{
return std::string(d->buffers.data());
}
void Socket::receive()
{
d->socket.async_read_some(boost::asio::buffer(d->buffers),
d->read.wrap(
boost::bind(&Socket::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
void Socket::handle()
{
assert(!d->targetHost.empty());
assert(!d->targetPort.empty());
std::string str(d->buffers.data());
std::clog << "Received: " << str << "." << std::endl;
if (str.substr(0, 4) == "PING")
write("PO" + str.substr(2) + "\r\n");
else if (str.find("MODE") != std::string::npos)
write("JOIN #OTland\r\n");
else if (str.find("JOIN") != std::string::npos)
write("PRIVMSG #OTland :Hello\r\n");
}
bool Socket::connected() const
{
return d->connected;
}
void handler(const std::string& fileName, const std::string& host, const std::string& port, uint32_t threads);
int main(int argc, char **argv)
{
if (argc < 5) {
std::clog << "[Error - main] Usage: " << argv[0] << " <proxy_file> <host> <port> <threads>" << std::endl;
return 1;
}
std::string file(argv[1]);
std::string host(argv[2]);
std::string port(argv[3]);
uint32_t threads = static_cast<uint32_t>(std::atoi(argv[4]));
if (!threads)
threads = 1;
for (uint32_t __i = 0; __i < threads; ++__i)
// FIXME: Use the thread.join() there.
handler(file, host, port, threads);
}
typedef std::vector<Socket*> SocketVec;
void handler(const std::string& fileName, const std::string& host,
const std::string& port, uint32_t threads)
{
assert(!fileName.empty());
assert(!host.empty());
assert(!port.empty());
ProxyVec proxies = loadProxies(fileName);
assert(proxies.size());
SocketVec sockets;
for (ProxyVec::const_iterator it = proxies.begin(); it != proxies.end(); ++it) {
boost::asio::io_service io;
Socket socket(io, (*it)->name, toString((*it)->port), host, port);
// FIXME: socket is a local variable and it's address is invalid outside
// this loop -> memory leak -> seg-fault.
sockets.push_back(&socket);
}
for (SocketVec::const_iterator it = sockets.begin(); it != sockets.end(); ++it) {
if (!(*it)->connected())
continue;
(*it)->handle();
}
// FIXME: I'm not sure if I understand this architecture. A new thread is
// started with this function as handler ? Who waits until this new created
// thread is finished ? Where is the join() ?
(void) new boost::thread(boost::bind(handler, fileName, host, port, threads));
}
答案 2 :(得分:1)
我认为这不是您唯一的问题,但在handler
的这个代码段中,您将在堆栈中创建Socket
个对象。您创建的每个Socket
对象将在for
循环结束时销毁。这意味着sockets
向量中的对象是无效对象。这样做也可能会破坏内存堆,足以产生您所看到的错误。
SocketVec sockets;
for (ProxyVec::const_iterator it = proxies.begin(); it != proxies.end(); ++it) {
boost::asio::io_service io;
Socket socket(io, (*it)->name, toString((*it)->port), host, port);
sockets.push_back(&socket);
}
将其更改为:
SocketVec sockets;
for (ProxyVec::const_iterator it = proxies.begin(); it != proxies.end(); ++it) {
boost::asio::io_service io;
Socket* socket = new Socket(io, (*it)->name, toString((*it)->port), host, port);
sockets.push_back(socket);
}
答案 3 :(得分:0)
这个答案最初是对Dan's答案的评论,但在看了你的代码后,我觉得有必要给出一个完整的答案。您真的需要仔细查看Boost.Asio examples并了解它们的工作原理。特别注意异步示例,看起来你并没有掌握对象生命周期的概念以及处理程序的工作方式。特别是,您应该在跳转到多个线程之前掌握单线程程序。当你已经征服了它时,你应该使用一个线程池来调用io_service::run
而不是每个线程io_service
。它最终将使您的程序逻辑更容易理解。
您还应该查看valgrind,您的代码中存在大量错误,例如:
==19853== Invalid read of size 4
==19853== at 0x10000D0E4: handler(std::string const&, std::string const&, std::string const&, unsigned int) (in ./a.out)
==19853== by 0x10000D5E6: main (in ./a.out)
==19853== Address 0x7fff5fbff398 is not stack'd, malloc'd or (recently) free'd