我有一个需要下载可变文件列表的应用程序(基于用户的更改,更改的内容等)。列表可以很短也可以很长(1000个文件)。我以要下载的每个线程的列表开始X工作者线程。如果我运行1个线程,则一切正常。如果我运行的线程数大于1,它将“可能”在__acrt_lock中崩溃(但是我不称其为)。问题出在winsock连接呼叫上。如果我将该通话注释掉,它将可以正常工作(显然不会下载文件,但不会崩溃)。
这是在旧的v110编译器链下使用的。我已经升级到v141链,现在出现了问题。当然,我正在使用多线程库。
我在不同的地方用过早的return语句“简化”了代码,并确定调用winsock函数“ connect”的一行是问题所在。没有使用全局变量(只有线程的私有本地存储)。
bool Socket::connect(const char * adrs, int port) {
lastErrCode = 0;
myIP = adrs;
myPort = port;
if (inet_addr(adrs) == INADDR_NONE) {
getHostByName(adrs, myIP);
}
else {
myIP = adrs;
}
if ((me = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
lastErrCode = WSAGetLastError();
return (false);
}
SOCKADDR_IN sock;
sock.sin_family = PF_INET;
sock.sin_port = htons(port);
sock.sin_addr.s_addr = inet_addr(myIP.str());
return(false); //:DEBUG:
if (::connect(me, (SOCKADDR*)&sock, sizeof(SOCKADDR)) == SOCKET_ERROR) {
lastErrCode = WSAGetLastError();
closesocket(me);
me = INVALID_SOCKET;
return (false);
}
return (true);
}
答案 0 :(得分:0)
感谢大家的回应。我已经解决了这个问题!我的主要代码没有愚蠢的Windows消息泵(我通常在Linux上运行这些类型的服务器)。我将其添加到主代码中,现在它可以正常工作。
#ifdef _WIN32
MSG msg;
while (!Stopped && GetMessage(&msg, (HWND)NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#else
while (!Stopped) {
Sleep(1000);
}
#endif
对不起,我没有足够的代码来实际运行示例,但是在调试和发行版本中,winsock代码都崩溃了100%。总是在RtlHeapxxx()或__acrt_lock()中崩溃。有了消息泵,我可以反复运行它。
对于gethostbyname问题,我正在调用内部的GetHostByName方法(区分大小写),并且它调用了较新的getaddrinfo()。
UINT32 Socket::getHostByName(const char * name, Data& ip) {
UINT32 iadrs = getHostByName(name);
ip.format("%d.%d.%d.%d", (iadrs >> 24) & 0xFF, (iadrs >> 16) & 0xFF, (iadrs >> 8) & 0xFF, iadrs & 0xFF);
return (iadrs);
}
UINT32 Socket::getHostByName(const char * name) {
if (lastAddress == name) {
return(lastResolution);
}
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo * result = nullptr;
if (getaddrinfo(name, "80", &hints, &result) != 0) {
if (result != nullptr) {
freeaddrinfo(result);
}
return (0);
}
for (struct addrinfo * ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
if (ptr->ai_family == AF_INET) {
struct sockaddr_in * ip = (struct sockaddr_in *) ptr->ai_addr;
UINT32 iadrs = (ip->sin_addr.S_un.S_un_b.s_b1 << 24) | (ip->sin_addr.S_un.S_un_b.s_b2 << 16) | (ip->sin_addr.S_un.S_un_b.s_b3 << 8) | (ip->sin_addr.S_un.S_un_b.s_b4);
freeaddrinfo(result);
lastAddress = name;
lastResolution = iadrs;
return (iadrs);
}
}
freeaddrinfo(result);
return (0);
}