MQTT AND Web Server connections within same sketch on NodeMCU - c++

I am unable to establish a http server connection and MQTT connection at the same time on an ESP8266 (Nodemcu) using libraries ESPAsyncWebServer and PubSubClient. My intention is to push over the air updates using the library AsyncElegantOTA while at the same time using MQTT for something else. Everything works great until I attempt to establish the HTTP server connection using the method below: setup_http(). I have tried establishing the connection within setup but that fails immediately and the connection cycles repeatedly. So, I have attempted to establish the connection within the loop function but that is failing as well. Is it possible to run both in the same sketch?
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <time.h>
#include "Secrets.h"
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
#define IOT_PUBLISH_TOPIC "pubout"
#define IOT_SUBSCRIBE_TOPIC "subin"
bool isServerStarted = false;
time_t now;
time_t nowish = 1510592825;
BearSSL::X509List cert(cacert);
BearSSL::X509List client_crt(client_cert);
BearSSL::PrivateKey key(privkey);
WiFiClientSecure net;
PubSubClient client(net);
void NTPConnect(void)
{
Serial.print("Setting time using SNTP");
configTime(TIME_ZONE * 3600, 0 * 3600, "pool.ntp.org", "time.nist.gov");
now = time(nullptr);
while (now < nowish)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("done!");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
}
String get_wifi_status()
{
switch (WiFi.status())
{
case WL_IDLE_STATUS:
return String("Wifi is changing modes.");
break;
case WL_NO_SSID_AVAIL:
return String("SSID: '") + WIFI_SSID + " is not available.";
break;
case WL_CONNECTED:
return String("Connected to ") + WIFI_SSID;
break;
case WL_CONNECT_FAILED:
return String("Could not connect to ") + WIFI_SSID;
break;
case WL_DISCONNECTED:
return String("Wifi not in station mode.");
break;
default:
return String("Wifi status error");
}
}
void setup_network()
{
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.mode(WIFI_STA);
Serial.println("");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print("Connecting to ");
Serial.print(WIFI_SSID);
Serial.println("...");
delay(1000);
}
Serial.println(get_wifi_status());
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void messageReceived(char *topic, byte *payload, unsigned int length)
{
//handle messages
}
void setup_mqtt()
{
delay(3000);
NTPConnect();
net.setTrustAnchors(&cert);
net.setClientRSACert(&client_crt, &key);
client.setServer(MQTT_HOST, 8883);
client.setCallback(messageReceived);
Serial.println("Connecting to IOT");
while (!client.connect(THINGNAME))
{
Serial.print(".");
delay(1000);
}
if (!client.connected())
{
Serial.println("IoT Timeout!");
return;
}
// Subscribe to a topic
client.subscribe(IOT_SUBSCRIBE_TOPIC);
Serial.println("IoT Connected!");
}
void setup_http()
{
AsyncWebServer server(80);
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(200, "text/plain", "Hi! I am a http server."); });
server.begin();
AsyncElegantOTA.begin(&server); // Start ElegantOTA
Serial.println("HTTP server started");
}
void setup()
{
Serial.begin(115200);
setup_network();
setup_mqtt();
// setup_http(); //Does not work here and crashes before MQTT connects. So, I moved to loop but that doesn't work either.
}
void loop()
{
now = time(nullptr);
if (!client.connected())
{
setup_mqtt();
}
if (isServerStarted == false)
{
Serial.println("Attempting to start http server");
delay(3000);
setup_http();
isServerStarted = true;
Serial.println("It crashes before we get here");
}
else
{
client.loop();
// BEGIN Loop code
}
}
Exception:
User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Unhandled C++ exception: OOM
>>>stack>>>
ctx: cont
sp: 3ffffd20 end: 3fffffc0 offset: 0000
3ffffd20: 3fff199c 3fff169c 000000ff 00000000
3ffffd30: 000000fe 00000000 00000000 00000000
3ffffd40: 00000000 00000000 00000000 00000001
3ffffd50: 3fff3198 00000000 3fff31a4 00000000
3ffffd60: 00000000 402089c6 00000c08 4021f12e
3ffffd70: 00000000 00000020 00000c08 4021f14d
3ffffd80: 3fff63ec 402089c6 00000c08 4021e832
3ffffd90: 3ffffda0 3ffffdec 3ffffde4 402089c6
3ffffda0: cca8cca9 00000000 3fff4554 40208bd6
3ffffdb0: c0afc0ae c027c023 c028c024 c013c009
3ffffdc0: c014c00a c031c02d c032c02e 00000000
3ffffdd0: c02ac026 c00ec004 c00fc005 009d009c
3ffffde0: c09dc09c c0a1c0a0 003d003c 0035002f
3ffffdf0: c012c008 c00dc003 0000000a 4021e813
3ffffe00: 00000000 3ffffe9c 3ffffe94 3fff6804
3ffffe10: 00000000 00000000 3fff4554 40209108
3ffffe20: 3fff1698 00000000 00000000 4025ebd3
3ffffe30: 007a1200 3fff4554 00000040 4025a222
3ffffe40: 007a1200 32087824 00000000 00000000
3ffffe50: 00000000 00000000 00000000 00000000
3ffffe60: 40106105 002da5e3 3fff13d8 00000000
3ffffe70: 3fff0af0 3fff13d8 00000001 00000000
3ffffe80: 00000000 00000000 00000000 00000000
3ffffe90: 00000000 3ffffe9c 00000000 4021f24a
3ffffea0: 3ffe8ff8 3fff4554 3fff61ec 402074f2
3ffffeb0: 3ffffee0 00000000 3fff1ac0 00000001
3ffffec0: 000022b3 3fff4554 3ffe8ff8 00000001
3ffffed0: 000022b3 3fff4554 3ffe8ff8 402093b4
3ffffee0: 40224b24 b781db12 40224b24 b781db12
3ffffef0: 00000000 00000000 3fff0ff8 40222932
3fffff00: 00004b4f 3fff4554 3fff0ff8 4020426c
3fffff10: 00000002 3fff1218 3fff610c 40220395
3fffff20: 00000000 00000000 3ffe8e9c 00000000
3fffff30: 00000000 3fff1218 3ffe967c 4021bce0
3fffff40: 4021bcd4 3fff1218 3ffe967c 3fff1370
3fffff50: 3fffdad0 3fff4554 3fff1044 40204518
3fffff60: 00000000 00000000 00000001 4021c200
3fffff70: 40224b24 3fff4554 3fff1044 40201e97
3fffff80: 402039cc feefeffe 40222b18 40222afc
3fffff90: 3fffdad0 00000000 3ffe88e4 40201f15
3fffffa0: feefeffe feefeffe feefeffe 4021ebb7
3fffffb0: feefeffe feefeffe feefeffe 40101225
<<<stack<<<
0x402089c6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::__allocated_ptr(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&, std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0>*) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:53
(inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:97
0x4021f12e in raise_exception at core_esp8266_postmortem.cpp:?
0x4021f14d in __unhandled_exception at ??:?
0x402089c6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::__allocated_ptr(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&, std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0>*) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:53
(inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:97
0x4021e832 in operator new(unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/abi.cpp:47
0x402089c6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::__allocated_ptr(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&, std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0>*) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:53
(inlined by) std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >(std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> >&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:97
0x40208bd6 in std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<br_x509_minimal_context, std::allocator<br_x509_minimal_context>, (__gnu_cxx::_Lock_policy)0> > >::get() at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/allocated_ptr.h:85
(inlined by) std::__shared_count<(__gnu_cxx::_Lock_policy)0>::__shared_count<br_x509_minimal_context, std::allocator<br_x509_minimal_context>>(br_x509_minimal_context*&, std::_Sp_alloc_shared_tag<std::allocator<br_x509_minimal_context> >) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h:681
(inlined by) std::__shared_ptr<br_x509_minimal_context, (__gnu_cxx::_Lock_policy)0>::__shared_ptr<std::allocator<br_x509_minimal_context>>(std::_Sp_alloc_shared_tag<std::allocator<br_x509_minimal_context> >) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr_base.h:1371
(inlined by) std::shared_ptr<br_x509_minimal_context>::shared_ptr<std::allocator<br_x509_minimal_context>>(std::_Sp_alloc_shared_tag<std::allocator<br_x509_minimal_context> >) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr.h:408
(inlined by) std::shared_ptr<br_x509_minimal_context> std::allocate_shared<br_x509_minimal_context, std::allocator<br_x509_minimal_context>>(std::allocator<br_x509_minimal_context> const&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr.h:860
(inlined by) std::shared_ptr<br_x509_minimal_context> std::make_shared<br_x509_minimal_context>() at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/shared_ptr.h:876
(inlined by) BearSSL::WiFiClientSecureCtx::_installClientX509Validator() at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.cpp:1063
0x4021e813 in operator new(unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/abi.cpp:41
0x40209108 in BearSSL::WiFiClientSecureCtx::_connectSSL(char const*) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.cpp:1134
0x4025ebd3 in ip_chksum_pseudo at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/lwip2/builder/lwip2-src/src/core/inet_chksum.c:395
0x4025a222 in tcp_output at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/lwip2/builder/lwip2-src/src/core/tcp_out.c:1361
0x40106105 in ets_timer_arm_new at ??:?
0x4021f24a in delay at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_wiring.cpp:54
0x402074f2 in ClientContext::connect(ip4_addr*, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/include/ClientContext.h:148
(inlined by) WiFiClient::connect(IPAddress, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClient.cpp:162
0x402093b4 in BearSSL::WiFiClientSecureCtx::connect(char const*, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.cpp:232
0x40224b24 in DhcpServer::add_end(unsigned char*) at ??:?
0x40224b24 in DhcpServer::add_end(unsigned char*) at ??:?
0x40222932 in BearSSL::WiFiClientSecure::connect(char const*, unsigned short) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.h:245
0x4020426c in PubSubClient::connect(char const*, char const*, char const*, char const*, unsigned char, bool, char const*, bool) at .pio\libdeps\nodemcu\PubSubClient\src/PubSubClient.cpp:190
0x40220395 in uart_write at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/uart.cpp:544
0x4021bce0 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:194
0x4021bcd4 in HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/HardwareSerial.h:191
0x40204518 in PubSubClient::connect(char const*) at .pio\libdeps\nodemcu\PubSubClient\src/PubSubClient.cpp:167
0x4021c200 in Print::println(char const*) at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/Print.cpp:194
0x40224b24 in DhcpServer::add_end(unsigned char*) at ??:?
0x40201e97 in setup_mqtt() at src/main.cpp:133
0x402039cc in messageReceived(char*, unsigned char*, unsigned int) at src/main.cpp:114
0x40222b18 in std::_Function_handler<void (char*, unsigned char*, unsigned int), void (*)(char*, unsigned char*, unsigned int)>::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h:271
0x40222afc in std::_Function_handler<void (char*, unsigned char*, unsigned int), void (*)(char*, unsigned char*, unsigned int)>::_M_invoke(std::_Any_data const&, char*&&, unsigned char*&&, unsigned int&&) at c:\users\myusername\.platformio\packages\toolchain-xtensa\xtensa-lx106-elf\include\c++\10.3.0\bits/std_function.h:289
0x40201f15 in setup at src/main.cpp:171
0x4021ebb7 in loop_wrapper() at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:198
0x40101225 in cont_wrapper at C:\Users\myusername\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/cont.S:81
last failed alloc call: 402089C6(3080)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
last failed alloc caller: 0x402089c6
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3460, room 16
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4
tail 4
chksum 0xc9
csum 0xc9
v000b9e90
~ld

In setup_http(), you declared server as a variable local to the function. That means when the function returns, the variable (and web server) will be destroyed, which will lead to some seriously undefined behavior, like a crash.
You need to make sure that server exists and is valid for the lifetime of the web server, so you should declare it outside of the function, as a global or static variable.
For instance,
AsyncWebServer server(80);
void setup_http()
{
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
{ request->send(200, "text/plain", "Hi! I am a http server."); });
server.begin();
...
This will ensure that server isn't destroyed while you're still using it.

Related

Double free or corruption when using asio

I made some modifications to this code snippet which is used to send\recieve ICMP packets through ASIO APIs.
Here are the modifications that I made(full code snippet is seen below):
using the standard version API instead of the corresponding API provided by Boost
using std::bind instead of boost::bind
starting to use shared pointer
using a shared pointer which points to pinger(i.e. std::shared_ptr<pinger> sp{new pinger(io_service, argv[1])};) instead of contructing an instance directly by the default constructor of pinger (i.e. pinger p(io_service, argv[1]);).
class pinger derives from std::enabled_shared_from_this<pinger> now
the second argument passed to boost::bind is not a this pointer anymore,I use shared_from_this() to pass a std::shared_pointer to std::bind.For exmple: my code is timer_.async_wait(std::bind(&pinger::start_send, shared_from_this()));, whereas the orignal one is timer_.async_wait(boost::bind(&pinger::handle_timeout, this));.
to avoid calling shared_from_this() in the constructor of class pinger, the start_send(); start_receive(); is moved out of the constructer and a new function named Init() is used to invoke these two aforemetioned functions.
using the non-throwing version asio::raw_socket::send_to and retrying to send ICMP packets when some error occurs.
socket_.send_to(request_buffer.data(), destination_); is replaced by socket_.send_to(request_buffer.data(), destination_, flags, error);
retry to send ICMP packets(by calling timer_.async_wait(std::bind(&pinger::start_send, shared_from_this())); when socket_.send_to faces to an error.
Here is my code snippet(icmp_header.hpp & ipv4_header.hpp are seen here):
#if 1
#include "icmp_header.hpp"
#include "ipv4_header.hpp"
#include <boost/asio.hpp>
#include <functional>
#include <iostream>
#include <istream>
#include <memory>
#include <ostream>
using boost::asio::deadline_timer;
using boost::asio::ip::icmp;
namespace posix_time = boost::posix_time;
class pinger : public std::enable_shared_from_this<pinger> {
public:
pinger(boost::asio::io_service &io_service, const char *destination)
: resolver_(io_service), socket_(io_service, icmp::v4()),
timer_(io_service), sequence_number_(0), num_replies_(0) {
icmp::resolver::query query(icmp::v4(), destination, "");
destination_ = *resolver_.resolve(query);
}
void init() {
start_send();
start_receive();
}
private:
void start_send() {
std::string body("\"Hello!\" from Asio ping.");
// Create an ICMP header for an echo request.
icmp_header echo_request;
echo_request.type(icmp_header::echo_request);
echo_request.code(0);
echo_request.identifier(get_identifier());
echo_request.sequence_number(++sequence_number_);
compute_checksum(echo_request, body.begin(), body.end());
// Encode the request packet.
boost::asio::streambuf request_buffer;
std::ostream os(&request_buffer);
os << echo_request << body;
// Send the request.
time_sent_ = posix_time::microsec_clock::universal_time();
boost::system::error_code error;
boost::asio::socket_base::message_flags flags;
socket_.send_to(request_buffer.data(), destination_, flags, error);
if (error) {
std::cout << "send_to failed1:" << error.message() << std::endl;
std::cout << "send_to failed2:" << std::endl;
timer_.expires_at(time_sent_ + posix_time::seconds(1));
timer_.async_wait(std::bind(&pinger::start_send, shared_from_this()));
} else {
// Wait up to five seconds for a reply.
num_replies_ = 0;
timer_.expires_at(time_sent_ + posix_time::seconds(5));
timer_.async_wait(std::bind(&pinger::handle_timeout, shared_from_this()));
}
}
void handle_timeout() {
if (num_replies_ == 0)
std::cout << "Request timed out" << std::endl;
// Requests must be sent no less than one second apart.
timer_.expires_at(time_sent_ + posix_time::seconds(1));
timer_.async_wait(std::bind(&pinger::start_send, shared_from_this()));
}
void start_receive() {
// Discard any data already in the buffer.
reply_buffer_.consume(reply_buffer_.size());
// Wait for a reply. We prepare the buffer to receive up to 64KB.
socket_.async_receive(reply_buffer_.prepare(65536),
std::bind(&pinger::handle_receive, shared_from_this(),
std::placeholders::_1,
std::placeholders::_2));
}
void handle_receive(boost::system::error_code error, std::size_t length) {
// The actual number of bytes received is committed to the buffer so that we
// can extract it using a std::istream object.
if (error) {
std::cout << "error in handle_receive:"
<< boost::system::system_error(error).what() << std::endl;
}
reply_buffer_.commit(length);
// Decode the reply packet.
std::istream is(&reply_buffer_);
ipv4_header ipv4_hdr;
icmp_header icmp_hdr;
is >> ipv4_hdr >> icmp_hdr;
// We can receive all ICMP packets received by the host, so we need to
// filter out only the echo replies that match the our identifier and
// expected sequence number.
if (is && icmp_hdr.type() == icmp_header::echo_reply &&
icmp_hdr.identifier() == get_identifier() &&
icmp_hdr.sequence_number() == sequence_number_) {
// If this is the first reply, interrupt the five second timeout.
if (num_replies_++ == 0)
timer_.cancel();
// Print out some information about the reply packet.
posix_time::ptime now = posix_time::microsec_clock::universal_time();
std::cout << length - ipv4_hdr.header_length() << " bytes from "
<< ipv4_hdr.source_address()
<< ": icmp_seq=" << icmp_hdr.sequence_number()
<< ", ttl=" << ipv4_hdr.time_to_live()
<< ", time=" << (now - time_sent_).total_milliseconds() << " ms"
<< std::endl;
}
start_receive();
}
static unsigned short get_identifier() {
#if defined(BOOST_WINDOWS)
return static_cast<unsigned short>(::GetCurrentProcessId());
#else
return static_cast<unsigned short>(::getpid());
#endif
}
icmp::resolver resolver_;
icmp::endpoint destination_;
icmp::socket socket_;
deadline_timer timer_;
unsigned short sequence_number_;
posix_time::ptime time_sent_;
boost::asio::streambuf reply_buffer_;
std::size_t num_replies_;
};
int main(int argc, char *argv[]) {
try {
if (argc != 2) {
std::cerr << "Usage: ping <host>" << std::endl;
#if !defined(BOOST_WINDOWS)
std::cerr << "(You may need to run this program as root.)" << std::endl;
#endif
return 1;
}
boost::asio::io_service io_service;
std::shared_ptr<pinger> sp{new pinger(io_service, argv[1])};
sp->init();
io_service.run();
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
}
#endif
The code snippet above works well when my local network is ok.Here is the output:
32 bytes from 192.168.1.51: icmp_seq=1, ttl=58, time=4 ms
32 bytes from 192.168.1.51: icmp_seq=2, ttl=58, time=3 ms
//omit...
//running a long long time
The program receives a signal SIGABRT and then aborts when I run sudo ifconfig wlp59s0 down on purpose(to make sure whether the program is stable or not). Here is the backstrace I got by GDB
sudo gdb -q ./modified_ping
Reading symbols from ./modified_ping...done.
(gdb) r 192.168.1.51
Starting program: /home/jhon/icmp/build/modified_ping 192.168.1.51
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
32 bytes from 192.168.1.51: icmp_seq=1, ttl=58, time=3 ms
32 bytes from 192.168.1.51: icmp_seq=2, ttl=58, time=4 ms
32 bytes from 192.168.1.51: icmp_seq=3, ttl=58, time=3 ms
32 bytes from 192.168.1.51: icmp_seq=4, ttl=58, time=3 ms //NOTE:manually run `ifconfig down` on purpose
send_to failed1:
send_to failed2:
*** Error in `/home/jhon/icmp/build/modified_ping': double free or corruption (!prev): 0x0000000000699f80 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777f5)[0x7ffff6dc07f5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8038a)[0x7ffff6dc938a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7ffff6dcd58c]
/home/jhon/icmp/build/modified_ping[0x44bcd6]
/home/jhon/icmp/build/modified_ping[0x44ae36]
/home/jhon/icmp/build/modified_ping[0x449b56]
/home/jhon/icmp/build/modified_ping[0x447e09]
/home/jhon/icmp/build/modified_ping[0x445403]
/home/jhon/icmp/build/modified_ping[0x44e005]
/home/jhon/icmp/build/modified_ping[0x43f347]
/home/jhon/icmp/build/modified_ping[0x44de00]
/home/jhon/icmp/build/modified_ping[0x44db4e]
/home/jhon/icmp/build/modified_ping[0x44d6eb]
/home/jhon/icmp/build/modified_ping[0x44d3b6]
/home/jhon/icmp/build/modified_ping[0x44d0d9]
/home/jhon/icmp/build/modified_ping[0x44c9c7]
/home/jhon/icmp/build/modified_ping[0x44c03f]
/home/jhon/icmp/build/modified_ping[0x44b257]
/home/jhon/icmp/build/modified_ping[0x439e94]
/home/jhon/icmp/build/modified_ping[0x43ca93]
/home/jhon/icmp/build/modified_ping[0x43c4e8]
/home/jhon/icmp/build/modified_ping[0x43cdac]
/home/jhon/icmp/build/modified_ping[0x436b34]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7ffff6d69840]
/home/jhon/icmp/build/modified_ping[0x4059a9]
======= Memory map: ========
00400000-00486000 r-xp 00000000 08:02 94506936 /home/jhon/icmp/build/modified_ping
00685000-00686000 r--p 00085000 08:02 94506936 /home/jhon/icmp/build/modified_ping
00686000-00687000 rw-p 00086000 08:02 94506936 /home/jhon/icmp/build/modified_ping
00687000-006b9000 rw-p 00000000 00:00 0 [heap]
7ffff0000000-7ffff0021000 rw-p 00000000 00:00 0
7ffff0021000-7ffff4000000 ---p 00000000 00:00 0
7ffff6d49000-7ffff6f09000 r-xp 00000000 08:02 14029372 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff6f09000-7ffff7109000 ---p 001c0000 08:02 14029372 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7109000-7ffff710d000 r--p 001c0000 08:02 14029372 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff710d000-7ffff710f000 rw-p 001c4000 08:02 14029372 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff710f000-7ffff7113000 rw-p 00000000 00:00 0
7ffff7113000-7ffff712a000 r-xp 00000000 08:02 14024978 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff712a000-7ffff7329000 ---p 00017000 08:02 14024978 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff7329000-7ffff732a000 r--p 00016000 08:02 14024978 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff732a000-7ffff732b000 rw-p 00017000 08:02 14024978 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff732b000-7ffff7433000 r-xp 00000000 08:02 14024798 /lib/x86_64-linux-gnu/libm-2.23.so
7ffff7433000-7ffff7632000 ---p 00108000 08:02 14024798 /lib/x86_64-linux-gnu/libm-2.23.so
7ffff7632000-7ffff7633000 r--p 00107000 08:02 14024798 /lib/x86_64-linux-gnu/libm-2.23.so
7ffff7633000-7ffff7634000 rw-p 00108000 08:02 14024798 /lib/x86_64-linux-gnu/libm-2.23.so
7ffff7634000-7ffff77a6000 r-xp 00000000 08:02 44435598 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7ffff77a6000-7ffff79a6000 ---p 00172000 08:02 44435598 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7ffff79a6000-7ffff79b0000 r--p 00172000 08:02 44435598 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7ffff79b0000-7ffff79b2000 rw-p 0017c000 08:02 44435598 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21
7ffff79b2000-7ffff79b6000 rw-p 00000000 00:00 0
7ffff79b6000-7ffff79b9000 r-xp 00000000 08:02 44441454 /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0
7ffff79b9000-7ffff7bb8000 ---p 00003000 08:02 44441454 /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0
7ffff7bb8000-7ffff7bb9000 r--p 00002000 08:02 44441454 /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0
7ffff7bb9000-7ffff7bba000 rw-p 00003000 08:02 44441454 /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0
7ffff7bba000-7ffff7bd2000 r-xp 00000000 08:02 14024729 /lib/x86_64-linux-gnu/libpthread-2.23.so
7ffff7bd2000-7ffff7dd1000 ---p 00018000 08:02 14024729 /lib/x86_64-linux-gnu/libpthread-2.23.so
7ffff7dd1000-7ffff7dd2000 r--p 00017000 08:02 14024729 /lib/x86_64-linux-gnu/libpthread-2.23.so
7ffff7dd2000-7ffff7dd3000 rw-p 00018000 08:02 14024729 /lib/x86_64-linux-gnu/libpthread-2.23.so
7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0
7ffff7dd7000-7ffff7dfd000 r-xp 00000000 08:02 14024795 /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7fcb000-7ffff7fd2000 rw-p 00000000 00:00 0
7ffff7ff6000-7ffff7ff7000 rw-p 00000000 00:00 0
7ffff7ff7000-7ffff7ffa000 r--p 00000000 00:00 0 [vvar]
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00025000 08:02 14024795 /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7ffd000-7ffff7ffe000 rw-p 00026000 08:02 14024795 /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Program received signal SIGABRT, Aborted.
0x00007ffff6d7e438 in __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: no such file or folder
(gdb) bt
#0 0x00007ffff6d7e438 in __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007ffff6d8003a in __GI_abort () at abort.c:89
#2 0x00007ffff6dc07fa in __libc_message (do_abort=do_abort#entry=2, fmt=fmt#entry=0x7ffff6ed9fd8 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff6dc938a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>, str=0x7ffff6eda108 "double free or corruption (!prev)", action=3) at malloc.c:5020
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3874
#5 0x00007ffff6dcd58c in __GI___libc_free (mem=<optimized out>) at malloc.c:2975
#6 0x000000000044bcd6 in __gnu_cxx::new_allocator<char>::deallocate (this=0x7fffffffdd98, __p=0x699f80 "\b") at /usr/include/c++/4.9/ext/new_allocator.h:110
#7 0x000000000044ae36 in std::allocator_traits<std::allocator<char> >::deallocate (__a=..., __p=0x699f80 "\b", __n=128) at /usr/include/c++/4.9/bits/alloc_traits.h:514
#8 0x0000000000449b56 in std::_Vector_base<char, std::allocator<char> >::_M_deallocate (this=0x7fffffffdd98, __p=0x699f80 "\b", __n=128) at /usr/include/c++/4.9/bits/stl_vector.h:178
#9 0x0000000000447e09 in std::_Vector_base<char, std::allocator<char> >::~_Vector_base (this=0x7fffffffdd98, __in_chrg=<optimized out>) at /usr/include/c++/4.9/bits/stl_vector.h:160
#10 0x0000000000445403 in std::vector<char, std::allocator<char> >::~vector (this=0x7fffffffdd98, __in_chrg=<optimized out>) at /usr/include/c++/4.9/bits/stl_vector.h:425
#11 0x000000000044e005 in boost::asio::basic_streambuf<std::allocator<char> >::~basic_streambuf (this=0x7fffffffdd50, __in_chrg=<optimized out>)
at /usr/include/boost/asio/basic_streambuf.hpp:111
#12 0x000000000043f347 in pinger::start_send (this=0x698d50) at /home/jhon/icmp/src/main.cpp:42
#13 0x000000000044de00 in std::_Mem_fn<void (pinger::*)()>::_M_call<std::shared_ptr<pinger>&> (this=0x7fffffffe140, __ptr=std::shared_ptr (count 4, weak 1) 0x698d50)
at /usr/include/c++/4.9/functional:526
#14 0x000000000044db4e in std::_Mem_fn<void (pinger::*)()>::operator()<std::shared_ptr<pinger>&, , void>(std::shared_ptr<pinger>&) const (this=0x7fffffffe140,
__object=std::shared_ptr (count 4, weak 1) 0x698d50) at /usr/include/c++/4.9/functional:578
#15 0x000000000044d6eb in std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>::__call<void, boost::system::error_code const&, 0ul>(std::tuple<boost::system::error_code const&>&&, std::_Index_tuple<0ul>) (this=0x7fffffffe140, __args=<unknown type in /home/jhon/icmp/build/modified_ping, CU 0xee6ae, DIE 0x1264e2>)
at /usr/include/c++/4.9/functional:1264
#16 0x000000000044d3b6 in std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>::operator()<boost::system::error_code const&, void>(boost::system::error_code const&) (
this=0x7fffffffe140) at /usr/include/c++/4.9/functional:1323
#17 0x000000000044d0d9 in boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>::operator()() (this=0x7fffffffe140)
---Type <return> to continue, or q <return> to quit---
at /usr/include/boost/asio/detail/bind_handler.hpp:47
#18 0x000000000044c9c7 in boost::asio::asio_handler_invoke<boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code> >(boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>&, ...) (function=...)
at /usr/include/boost/asio/handler_invoke_hook.hpp:69
#19 0x000000000044c03f in boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>, std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)> >(boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>&, std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>&) (function=..., context=...) at /usr/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#20 0x000000000044b257 in boost::asio::detail::wait_handler<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)> >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) (owner=0x698c70, base=0x699af0) at /usr/include/boost/asio/detail/wait_handler.hpp:70
#21 0x0000000000439e94 in boost::asio::detail::task_io_service_operation::complete (this=0x699af0, owner=..., ec=..., bytes_transferred=0)
at /usr/include/boost/asio/detail/task_io_service_operation.hpp:38
#22 0x000000000043ca93 in boost::asio::detail::task_io_service::do_run_one (this=0x698c70, lock=..., this_thread=..., ec=...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:372
#23 0x000000000043c4e8 in boost::asio::detail::task_io_service::run (this=0x698c70, ec=...) at /usr/include/boost/asio/detail/impl/task_io_service.ipp:149
#24 0x000000000043cdac in boost::asio::io_service::run (this=0x7fffffffe360) at /usr/include/boost/asio/impl/io_service.ipp:59
#25 0x0000000000436b34 in main (argc=2, argv=0x7fffffffe498) at /home/jhon/icmp/src/main.cpp:155
Valgrind:
Thanks to #Basile Starynkevitch.
I try to use valgrind to figure out the problem.I add add_compile_options(-Wall -Wextra) in the CMakeLists.txt(set (CMAKE_BUILD_TYPE debug) has already been there when debugging with GDB). I recompile the code sippet above and run it with sudo valgrind .... But what surprises me is that no signal is received now.
Here is the output which is seen in the terminal (with valgrind on Ubuntu 16.04):
sudo valgrind --log-file=valgrind.log --error-limit=no --leak-check=full --tool=memcheck --show-reachable=yes ./modified_ping 192.168.1.51
32 bytes from 192.168.1.51: icmp_seq=1, ttl=58, time=90 ms
32 bytes from 192.168.1.51: icmp_seq=2, ttl=58, time=7 ms
32 bytes from 192.168.1.51: icmp_seq=3, ttl=58, time=11 ms
32 bytes from 192.168.1.51: icmp_seq=4, ttl=58, time=4 ms
32 bytes from 192.168.1.51: icmp_seq=5, ttl=58, time=3 ms
32 bytes from 192.168.1.51: icmp_seq=6, ttl=58, time=2 ms
send_to failed1:
send_to failed2:
send_to failed1:
send_to failed2:
send_to failed1:
send_to failed2:
//omit...
Here is what the valgrind.log contains:
NOTE:1.since the program runs infinitely with valgrind, the program is stopped by CTRL+C. It's strange that the same binary program still encounters SIGABRT with sudo gdb ... when ifconfig down is called in purpose.
2.The log is huge, full log is seen at here.
sudo valgrind --log-file=valgrind.log --error-limit=no --leak-check=full --tool=memcheck --show-reachable=yes ./modified_ping 192.168.1.51
==9362== Memcheck, a memory error detector
==9362== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9362== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9362== Command: ./modified_ping 192.168.1.51
//...full log is seen at https://coliru.stacked-
==9362== 1,265 bytes in 55 blocks are definitely lost in loss record 18 of 20
==9362== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9362== by 0x505823E: ??? (in /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0)
==9362== by 0x5058BFD: ??? (in /usr/lib/x86_64-linux-gnu/libboost_system.so.1.58.0)
==9362== by 0x43731A: boost::system::error_code::message() const (error_code.hpp:357)
==9362== by 0x43F0E9: pinger::start_send() (main.cpp:53)
==9362== by 0x44DDFF: void std::_Mem_fn<void (pinger::*)()>::_M_call<std::shared_ptr<pinger>&>(std::shared_ptr<pinger>&, void const volatile*) const (in /home/jhon/icmp/build/modified_ping)
==9362== by 0x44DB4D: void std::_Mem_fn<void (pinger::*)()>::operator()<std::shared_ptr<pinger>&, , void>(std::shared_ptr<pinger>&) const (functional:578)
==9362== by 0x44D6EA: void std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>::__call<void, boost::system::error_code const&, 0ul>(std::tuple<boost::system::error_code const&>&&, std::_Index_tuple<0ul>) (functional:1264)
==9362== by 0x44D3B5: void std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>::operator()<boost::system::error_code const&, void>(boost::system::error_code const&) (functional:1323)
==9362== by 0x44D0D8: boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>::operator()() (bind_handler.hpp:47)
==9362== by 0x44C9C6: void boost::asio::asio_handler_invoke<boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code> >(boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>&, ...) (handler_invoke_hook.hpp:69)
==9362== by 0x44C03E: void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>, std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)> >(boost::asio::detail::binder1<std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>, boost::system::error_code>&, std::_Bind<std::_Mem_fn<void (pinger::*)()> (std::shared_ptr<pinger>)>&) (handler_invoke_helpers.hpp:37)
==9362==
==9362== 65,536 bytes in 1 blocks are still reachable in loss record 19 of 20
==9362== at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9362== by 0x44BD8B: __gnu_cxx::new_allocator<char>::allocate(unsigned long, void const*) (new_allocator.h:104)
==9362== by 0x44AEB9: std::allocator_traits<std::allocator<char> >::allocate(std::allocator<char>&, unsigned long) (alloc_traits.h:488)
==9362== by 0x449CBB: std::_Vector_base<char, std::allocator<char> >::_M_allocate(unsigned long) (stl_vector.h:170)
==9362== by 0x447F2D: std::vector<char, std::allocator<char> >::_M_default_append(unsigned long) (vector.tcc:557)
==9362== by 0x44547E: std::vector<char, std::allocator<char> >::resize(unsigned long) (stl_vector.h:676)
==9362== by 0x445C4F: boost::asio::basic_streambuf<std::allocator<char> >::reserve(unsigned long) (basic_streambuf.hpp:326)
==9362== by 0x442D04: boost::asio::basic_streambuf<std::allocator<char> >::prepare(unsigned long) (basic_streambuf.hpp:207)
==9362== by 0x43F6B5: pinger::start_receive() (main.cpp:82)
==9362== by 0x43EDE1: pinger::init() (main.cpp:26)
==9362== by 0x436B27: main (main.cpp:154)
==9362==
==9362== 72,704 bytes in 1 blocks are still reachable in loss record 20 of 20
==9362== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9362== by 0x52E4EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21)
==9362== by 0x40106F9: call_init.part.0 (dl-init.c:72)
==9362== by 0x401080A: call_init (dl-init.c:30)
==9362== by 0x401080A: _dl_init (dl-init.c:120)
==9362== by 0x4000C69: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so)
==9362== by 0x1: ???
==9362== by 0xFFF000652: ???
==9362== by 0xFFF000662: ???
==9362==
==9362== LEAK SUMMARY:
==9362== definitely lost: 1,265 bytes in 55 blocks
==9362== indirectly lost: 0 bytes in 0 blocks
==9362== possibly lost: 0 bytes in 0 blocks
==9362== still reachable: 139,978 bytes in 19 blocks
==9362== suppressed: 0 bytes in 0 blocks
==9362==
==9362== For counts of detected and suppressed errors, rerun with: -v
==9362== Use --track-origins=yes to see where uninitialised values come from
==9362== ERROR SUMMARY: 337 errors from 5 contexts (suppressed: 0 from 0)
What's more, it's strange that no signal would be recieved anymore if std::cout << "send_to failed1:" << error.message() << std::endl; is commented out when sudo ifconfig wlp59s0 down has been called. I don't think the problem is with this expression.But I really can't figure out where goes wrong. Could somebody shed some light on this matter?
(gdb) make //after commenting out `std::cout << "send_to failed1:" << error.message() << std::endl;`
[100%] Built target modified_ping
(gdb) r 192.168.1.51
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/jhon/icmp/build/modified_ping 192.168.1.51
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
32 bytes from 192.168.1.51: icmp_seq=1, ttl=58, time=4 ms
32 bytes from 192.168.1.51: icmp_seq=2, ttl=58, time=7 ms
32 bytes from 192.168.1.51: icmp_seq=3, ttl=58, time=2 ms
32 bytes from 192.168.1.51: icmp_seq=4, ttl=58, time=3 ms
32 bytes from 192.168.1.51: icmp_seq=5, ttl=58, time=3 ms
32 bytes from 192.168.1.51: icmp_seq=6, ttl=58, time=4 ms
32 bytes from 192.168.1.51: icmp_seq=7, ttl=58, time=4 ms
32 bytes from 192.168.1.51: icmp_seq=8, ttl=58, time=5 ms
32 bytes from 192.168.1.51: icmp_seq=9, ttl=58, time=3 ms
32 bytes from 192.168.1.51: icmp_seq=10, ttl=58, time=2 ms
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
send_to failed2:
Extra Information:
I am using boost-1.58 which is installed by sudo apt-get install libboost-all-dev on ubuntu16.04.
UPDATED:
Thanks to #273K's generous help.
But the double free or corruption seems not caused by the wrong declaration of handle_receive() because even if the program which does not invoke handle_receive() anymore still faces a similar problem. Here is the backtrace.
I tried your code. The first error faced: error C4700: uninitialized local variable 'flags' used. I have corrected the definition:
boost::asio::socket_base::message_flags flags{};
You have extended void handle_receive(std::size_t length) from the example to
void handle_receive(boost::system::error_code error, std::size_t length). This is incorrect. According to the manual basic_raw_socket::async_receive, it must receive error by const reference.
void handle_receive(const boost::system::error_code &error,
std::size_t length)
After fixing those errors, the SIGABRT went away.
error.message() is supposed to access error by reference, but your definition directs the compiler to access error on the stack, that results in stack memory corruption, because the caller of handle_receive places sizeof(void*) bytes on the stack or in a CPU register, but error.message() uses sizeof(boost::system::error_code) bytes on the stack.
The line expression
boost::system::system_error(error)
could be
error.message()
Now, the fact that it crashes gives me the idea that you might be finding conflicting/incompatible versions of Boost System at runtime vs. at compile time. I know that boost::error_code received some layout-incompatible changes over time.
Another source of such compatibility problem is when the linked libraries are built with very different compiler flags.
Use tools like ldd to check what libraries are actually found at runtime, and whether there are surprises. Also, check the preprocessed source (or e.g. BOOST_VERSION) to see that no surprise header versions are picked up where you didn't expect them.
Inverting the burden of proof, I have created a docker environment to test your code and see that the problem is not reproduced, perhaps you can compare: ubu1604.zip containing:
File Dockerfile
FROM ubuntu:16.04
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get -qyy update
RUN apt-get -qyy install build-essential screen cmake
RUN apt-get -qyy install libboost-all-dev
COPY so /so
# build
WORKDIR /so
RUN cmake . -Wno-dev && make;
ENTRYPOINT [ "/so/test" ]
File so/CMakeLists.txt
SET(CMAKE_CXX_STANDARD 11)
ADD_EXECUTABLE(test test.cpp)
find_package(Boost COMPONENTS system REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS -pthread)
target_link_libraries(test ${Boost_LIBRARIES})
File so/icmp_header.hpp
//
// icmp_header.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ICMP_HEADER_HPP
#define ICMP_HEADER_HPP
#include <istream>
#include <ostream>
#include <algorithm>
// ICMP header for both IPv4 and IPv6.
//
// The wire format of an ICMP header is:
//
// 0 8 16 31
// +---------------+---------------+------------------------------+ ---
// | | | | ^
// | type | code | checksum | |
// | | | | |
// +---------------+---------------+------------------------------+ 8 bytes
// | | | |
// | identifier | sequence number | |
// | | | v
// +-------------------------------+------------------------------+ ---
class icmp_header
{
public:
enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4,
redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12,
timestamp_request = 13, timestamp_reply = 14, info_request = 15,
info_reply = 16, address_request = 17, address_reply = 18 };
icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }
unsigned char type() const { return rep_[0]; }
unsigned char code() const { return rep_[1]; }
unsigned short checksum() const { return decode(2, 3); }
unsigned short identifier() const { return decode(4, 5); }
unsigned short sequence_number() const { return decode(6, 7); }
void type(unsigned char n) { rep_[0] = n; }
void code(unsigned char n) { rep_[1] = n; }
void checksum(unsigned short n) { encode(2, 3, n); }
void identifier(unsigned short n) { encode(4, 5, n); }
void sequence_number(unsigned short n) { encode(6, 7, n); }
friend std::istream& operator>>(std::istream& is, icmp_header& header)
{ return is.read(reinterpret_cast<char*>(header.rep_), 8); }
friend std::ostream& operator<<(std::ostream& os, const icmp_header& header)
{ return os.write(reinterpret_cast<const char*>(header.rep_), 8); }
private:
unsigned short decode(int a, int b) const
{ return (rep_[a] << 8) + rep_[b]; }
void encode(int a, int b, unsigned short n)
{
rep_[a] = static_cast<unsigned char>(n >> 8);
rep_[b] = static_cast<unsigned char>(n & 0xFF);
}
unsigned char rep_[8];
};
template <typename Iterator>
void compute_checksum(icmp_header& header,
Iterator body_begin, Iterator body_end)
{
unsigned int sum = (header.type() << 8) + header.code()
+ header.identifier() + header.sequence_number();
Iterator body_iter = body_begin;
while (body_iter != body_end)
{
sum += (static_cast<unsigned char>(*body_iter++) << 8);
if (body_iter != body_end)
sum += static_cast<unsigned char>(*body_iter++);
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
header.checksum(static_cast<unsigned short>(~sum));
}
#endif // ICMP_HEADER_HPP
File so/ipv4_header.hpp
//
// ipv4_header.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef IPV4_HEADER_HPP
#define IPV4_HEADER_HPP
#include <algorithm>
#include <boost/asio/ip/address_v4.hpp>
// Packet header for IPv4.
//
// The wire format of an IPv4 header is:
//
// 0 8 16 31
// +-------+-------+---------------+------------------------------+ ---
// | | | | | ^
// |version|header | type of | total length in bytes | |
// | (4) | length| service | | |
// +-------+-------+---------------+-+-+-+------------------------+ |
// | | | | | | |
// | identification |0|D|M| fragment offset | |
// | | |F|F| | |
// +---------------+---------------+-+-+-+------------------------+ |
// | | | | |
// | time to live | protocol | header checksum | 20 bytes
// | | | | |
// +---------------+---------------+------------------------------+ |
// | | |
// | source IPv4 address | |
// | | |
// +--------------------------------------------------------------+ |
// | | |
// | destination IPv4 address | |
// | | v
// +--------------------------------------------------------------+ ---
// | | ^
// | | |
// / options (if any) / 0 - 40
// / / bytes
// | | |
// | | v
// +--------------------------------------------------------------+ ---
class ipv4_header
{
public:
ipv4_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }
unsigned char version() const { return (rep_[0] >> 4) & 0xF; }
unsigned short header_length() const { return (rep_[0] & 0xF) * 4; }
unsigned char type_of_service() const { return rep_[1]; }
unsigned short total_length() const { return decode(2, 3); }
unsigned short identification() const { return decode(4, 5); }
bool dont_fragment() const { return (rep_[6] & 0x40) != 0; }
bool more_fragments() const { return (rep_[6] & 0x20) != 0; }
unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; }
unsigned int time_to_live() const { return rep_[8]; }
unsigned char protocol() const { return rep_[9]; }
unsigned short header_checksum() const { return decode(10, 11); }
boost::asio::ip::address_v4 source_address() const
{
boost::asio::ip::address_v4::bytes_type bytes
= { { rep_[12], rep_[13], rep_[14], rep_[15] } };
return boost::asio::ip::address_v4(bytes);
}
boost::asio::ip::address_v4 destination_address() const
{
boost::asio::ip::address_v4::bytes_type bytes
= { { rep_[16], rep_[17], rep_[18], rep_[19] } };
return boost::asio::ip::address_v4(bytes);
}
friend std::istream& operator>>(std::istream& is, ipv4_header& header)
{
is.read(reinterpret_cast<char*>(header.rep_), 20);
if (header.version() != 4)
is.setstate(std::ios::failbit);
std::streamsize options_length = header.header_length() - 20;
if (options_length < 0 || options_length > 40)
is.setstate(std::ios::failbit);
else
is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length);
return is;
}
private:
unsigned short decode(int a, int b) const
{ return (rep_[a] << 8) + rep_[b]; }
unsigned char rep_[60];
};
#endif // IPV4_HEADER_HPP
File so/test.cpp
#include "icmp_header.hpp"
#include "ipv4_header.hpp"
#include <boost/asio.hpp>
#include <functional>
#include <iostream>
#include <istream>
#include <memory>
#include <ostream>
using boost::asio::deadline_timer;
using boost::asio::ip::icmp;
namespace posix_time = boost::posix_time;
class pinger : public std::enable_shared_from_this<pinger> {
public:
pinger(boost::asio::io_service& io_service, const char* destination)
: resolver_(io_service)
, socket_(io_service, icmp::v4())
, timer_(io_service)
, sequence_number_(0)
, num_replies_(0) {
icmp::resolver::query query(icmp::v4(), destination, "");
destination_ = *resolver_.resolve(query);
}
void init() {
start_send();
start_receive();
}
private:
void start_send() {
std::string body("\"Hello!\" from Asio ping.");
// Create an ICMP header for an echo request.
icmp_header echo_request;
echo_request.type(icmp_header::echo_request);
echo_request.code(0);
echo_request.identifier(get_identifier());
echo_request.sequence_number(++sequence_number_);
compute_checksum(echo_request, body.begin(), body.end());
// Encode the request packet.
boost::asio::streambuf request_buffer;
std::ostream os(&request_buffer);
os << echo_request << body;
// Send the request.
time_sent_ = posix_time::microsec_clock::universal_time();
boost::system::error_code error;
boost::asio::socket_base::message_flags flags{};
socket_.send_to(request_buffer.data(), destination_, flags, error);
if (error) {
std::cout << "send_to failed1:" << error.message() << std::endl;
std::cout << "send_to failed2:" << std::endl;
timer_.expires_at(time_sent_ + posix_time::seconds(1));
timer_.async_wait(
std::bind(&pinger::start_send, shared_from_this()));
} else {
// Wait up to five seconds for a reply.
num_replies_ = 0;
timer_.expires_at(time_sent_ + posix_time::seconds(5));
timer_.async_wait(
std::bind(&pinger::handle_timeout, shared_from_this()));
}
}
void handle_timeout() {
if (num_replies_ == 0)
std::cout << "Request timed out" << std::endl;
// Requests must be sent no less than one second apart.
timer_.expires_at(time_sent_ + posix_time::seconds(1));
timer_.async_wait(std::bind(&pinger::start_send, shared_from_this()));
}
void start_receive() {
// Discard any data already in the buffer.
reply_buffer_.consume(reply_buffer_.size());
// Wait for a reply. We prepare the buffer to receive up to 64KB.
socket_.async_receive(
reply_buffer_.prepare(65536),
std::bind(&pinger::handle_receive, shared_from_this(),
std::placeholders::_1, std::placeholders::_2));
}
void handle_receive(boost::system::error_code error, std::size_t length) {
// The actual number of bytes received is committed to the buffer so
// that we can extract it using a std::istream object.
if (error) {
std::cout << "error in handle_receive:"
<< boost::system::system_error(error).what() << std::endl;
}
reply_buffer_.commit(length);
// Decode the reply packet.
std::istream is(&reply_buffer_);
ipv4_header ipv4_hdr;
icmp_header icmp_hdr;
is >> ipv4_hdr >> icmp_hdr;
// We can receive all ICMP packets received by the host, so we need to
// filter out only the echo replies that match the our identifier and
// expected sequence number.
if (is && icmp_hdr.type() == icmp_header::echo_reply &&
icmp_hdr.identifier() == get_identifier() &&
icmp_hdr.sequence_number() == sequence_number_) {
// If this is the first reply, interrupt the five second timeout.
if (num_replies_++ == 0)
timer_.cancel();
// Print out some information about the reply packet.
posix_time::ptime now =
posix_time::microsec_clock::universal_time();
std::cout << length - ipv4_hdr.header_length() << " bytes from "
<< ipv4_hdr.source_address()
<< ": icmp_seq=" << icmp_hdr.sequence_number()
<< ", ttl=" << ipv4_hdr.time_to_live()
<< ", time=" << (now - time_sent_).total_milliseconds()
<< " ms" << std::endl;
}
start_receive();
}
static unsigned short get_identifier() {
#if defined(BOOST_WINDOWS)
return static_cast<unsigned short>(::GetCurrentProcessId());
#else
return static_cast<unsigned short>(::getpid());
#endif
}
icmp::resolver resolver_;
icmp::endpoint destination_;
icmp::socket socket_;
deadline_timer timer_;
unsigned short sequence_number_;
posix_time::ptime time_sent_;
boost::asio::streambuf reply_buffer_;
std::size_t num_replies_;
};
int main(int argc, char *argv[]) {
try {
if (argc != 2) {
std::cerr << "Usage: ping <host>" << std::endl;
return 1;
}
boost::asio::io_service io_service;
auto sp = std::make_shared<pinger>(io_service, argv[1]);
sp->init();
io_service.run();
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
}
Build:
docker build -t sopingtest
Run:
docker run --rm -it sopingtest
Demo

C++ Problem with Vector Iterator on ESP8266 Microcontroller

I'm currently facing an issue with a vector iterator in C++. The application runs on an ESP8266 NodeMCU microcontroller. As soon as I call the function CWebServer::getAvailableNetworks() (implementation can be found below), the program crashes and I get the following error:
User exception (panic/abort/assert)
Abort called
>>>stack>>>
ctx: cont
sp: 3ffffd10 end: 3fffffc0 offset: 0000
3ffffd10: 00000000 00000000 00000000 00000000
3ffffd20: 000000fe 00000000 00000000 00000000
3ffffd30: 00000000 00000000 00000000 b8b1aabc
3ffffd40: 3ffefd60 3fff44cc 00000000 40205e9c
3ffffd50: 3fff451c 00000001 3fff44fc 4020e7ea
3ffffd60: 00000000 00000000 00000000 4020e7fc
3ffffd70: 00000000 3ffffe0c 00000000 4020e219
3ffffd80: 3ffffe04 00000000 00000000 00000000
3ffffd90: 00000000 00000000 00000000 40226fac
3ffffda0: 00000000 40205e9c 3fff451c 40226fbd
3ffffdb0: 3fff44fc 3fff44cc 3fff44fc 402277d8
3ffffdc0: 00000000 00000000 3fff44fc 4020e224
3ffffdd0: 40000000 00000000 00000000 00000000
3ffffde0: 00000000 00000000 00000000 40226fac
3ffffdf0: 3ffefb6c 40205e9c 3fff451c 40226fbd
3ffffe00: 3fff44fc 4022770c 3fff44fc 40227783
3ffffe10: 3fff451c 00000001 3ffffe80 40209f32
3ffffe20: 3ffe90e4 3fffc200 3ffe90f1 4022f3b3
3ffffe30: 3fff43dc 3ffefa4c 3ffe8a37 4020ca74
3ffffe40: 4020ca68 3ffefa4c 3ffe8a37 40205e9c
3ffffe50: 00000001 3ffffe8c 3ffe90e5 4022f3f6
3ffffe60: 3ffffe80 00000001 3ffefa4c 40205e9c
3ffffe70: 00000001 00000001 3ffefa4c 40209915
3ffffe80: 00000000 00000000 00000000 3fff43e8
3ffffe90: 00000001 00000001 00000020 401009b7
3ffffea0: 3fff3d4c 3fffff00 3ffffee0 40205e9c
3ffffeb0: 00000001 00000001 3fff3c54 4021837a
3ffffec0: 3fffff00 3ffef94c 3fff3c54 401000e1
3ffffed0: 3fff3c54 3ffef94c 3fff3c54 40205ed8
3ffffee0: 3fff3d00 0015001f 8015001f 80fe8614
3ffffef0: 3fff3c54 3ffef94c 3ffef90c 40208526
3fffff00: 3fff3d4c 0015001f 00c6a700 00000000
3fffff10: 807a1200 3fff4400 0000005f 80007641
3fffff20: 3ffef94c 00000001 402183ac 00000001
3fffff30: 00000001 00000000 00001388 4020bb3e
3fffff40: 00000000 3fff43a4 3ffef90c 3ffefac8
3fffff50: 00000001 3ffef930 3ffef90c 402093ec
3fffff60: 40218d50 00000000 00001388 4020ca74
3fffff70: 00000000 3fff43a4 3ffe8a37 4020cd39
3fffff80: 3fffdad0 00000000 3ffefa88 402094b0
3fffff90: 3fffdad0 00000000 3ffefa88 4020a140
3fffffa0: feefeffe feefeffe 3ffefa88 4020e454
3fffffb0: feefeffe feefeffe 3ffe8614 40100cb9
<<<stack<<<
ets Jan 8 2013,rst cause:1, boot mode:(3,7)
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
Here is the function that causes the problem ():
void CWebServer::getAvailableNetworks()
{
Serial.println("Get network scan result.");
bool statusSend = false;
try
{
std::string output = "{\"networks\":";
std::vector<sWiFi_Data*> data = CWiFiConnection::getAvailableNetworks();
if(data.size() <= 0)
{
output += "{}";
}
for(std::vector<sWiFi_Data*>::iterator it = data.begin(); it != data.end(); ++it)
{
// This line is for testing. Later on the JSON output will be calculated here from the Vector.
Serial.println(((*it)->SSID).c_str());
}
output += "}";
statusSend = true;
server.send(200, "application/json", output.c_str());
} catch(ScanException& e)
{
statusSend = true;
server.send(425);
} catch(std::exception e)
{
statusSend = true;
server.send(500);
Serial.println();
Serial.println("Unknown Exception while getting the network data:");
Serial.println(e.what());
Serial.println();
}
if(!statusSend) server.send(500);
}
This function should send the results of a network scan to the client. The network scan is simply done by calling the function WiFi.scanNetworks(true, true); which is part of the ESP8266WiFi.
The problem is caused by the line Serial.println(((*it)->SSID).c_str());
As soon as the program gets to this point, the error will show up and the program crashes. If I just delete this line and don't touch the vector at all, everything runs fine. So I assume that the vector iterator is the bad guy here.
Just for completence: as you can see the vector stores pointer to structs of type "sWiFi_Data".
This struct is defined in another class (the class that handles the WiFi connection) and it looks like this:
struct sWiFi_Data
{
std::string SSID;
std::string BSSID;
int32_t RSSI;
uint8_t channel;
uint8_t encryptionType;
bool isHidden;
};
As you may have noticed inside the CWebServer::getAvailableNetworks() function, the vector is the result of another function ( CWiFiConnection::getAvailableNetworks(); ). This function is inside the CWiFiConnection class. It looks like this:
std::vector<sWiFi_Data*> CWiFiConnection::getAvailableNetworks()
{
std::vector<sWiFi_Data*> data;
int8_t n = WiFi.scanComplete();
if(n == -1) throw ScanException("Warning: Trying to access network scan data while scan is not completed yet.");
if(n == -2) throw ScanException("Warning: Trying to access network scan, but scan was never triggered.");
if(n >= 0)
{
for(int i = 0; i < n; i++)
{
uint8_t encrytptionType = 0;
switch(WiFi.encryptionType(i)) {
case ENC_TYPE_NONE:
encrytptionType = 1; // None, Open Network
case ENC_TYPE_WEP:
encrytptionType = 2; // WEP
case ENC_TYPE_TKIP:
encrytptionType = 3; // WPA
case ENC_TYPE_CCMP:
encrytptionType = 4; // WPA 2
case ENC_TYPE_AUTO:
encrytptionType = 5; // Auto
default:
encrytptionType = 0; // Unknown
}
sWiFi_Data wifiData;
wifiData.SSID = WiFi.SSID(i).c_str();
wifiData.BSSID = WiFi.BSSIDstr(i).c_str();
wifiData.RSSI = WiFi.RSSI(i);
wifiData.channel = WiFi.channel(i);
wifiData.encryptionType = encrytptionType;
wifiData.isHidden = WiFi.isHidden(i);
data.push_back(&wifiData);
}
WiFi.scanDelete();
return data;
} else
{
throw ScanException("Warning: No networks found.");
}
}
By the way: the ScanException is just a generic exception that I wrote. Nothing fancy so I don't think that I would need to include the code here.
And just to clarify things, the procedure of communication looks like this:
Client send request to scan networks.
Server just calls the method: WiFi.scanNetworks(true, true); (Parameters: bool async, bool showHidden)
Because the scan is asynchronous, the client checks the result by sending a request to the server.
The server always responds to these requests by calling the CWebServer::getAvailableNetworks() function (our problem function).
In theory this function should reply with a code 425 ("not ready yet") if the result isn't there yet and should send the data of all available networks as a JSON if the scan is finished (this will be implemented where the line Serial.println(((*it)->SSID).c_str()); currently is.
By the way: I also tried to just output the vector's size inside the console. This works fine. So there are definitely values inside the vector.
Hope that anyone can help me out here. Thanks a lot.
Jannis
ps.: A documentation with examples for the network scan on an ESP8266 can be found here: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/scan-examples.html
This line: data.push_back(&wifiData); stores the address of a temporary object wifiData which will be destroyed once the scope, i.e the enclosing for-loop iteration, is exited.
When you then later access any of these addresses it will (probably) cause a seg fault (if you are lucky).
Instead of having a std::vector<sWiFi_Data*> better use a std::vector<sWiFi_Data>

mmap error : segmentation fault/invalid pointer error

I am new to mmap and still learning it . Based on my understanding i have created class for mmap which will be used to map a file in memory . The entire class is working fine but problem is coming when destructor is called ..the problem is segmentation fault or invalid pointer error is coming at the end of main function ...I have posted code of my class and main function which is using that class ...
Map.h
class MapData
{
public :
MapData();
~MapData();
MapData(char []);
bool OPEN();
void fnClose();
long fnGetSize();
char * fnGetFileRef();
char * ReadNextData(int );
private :
char * ptrRecord;
char ptrFileNm[250+1];
int fd;
struct stat sbuf;
bool bSuccess;
long sTotalSize;
char acData[2000+1];
long lCurrRead;
};
MapData.cpp
MapData::MapData()
{
}
MapData::~MapData()
{
printf("Inside MADATA Destructor \n ");
}
MapData::MapData(char acInput[])
{
strcpy(ptrFileNm,acInput);
sTotalSize=0;
lCurrRead=0;
bSuccess=false;
}
bool MapData::OPEN()
{
// if failed return false flg
if ((fd = open(ptrFileNm, O_RDONLY)) == -1) {
return bSuccess;
}
if (stat(ptrFileNm, &sbuf) == -1) {
return bSuccess;
}
// copy in local variable
sTotalSize = sbuf.st_size;
ptrRecord = (char * )mmap( (caddr_t)0, sTotalSize, PROT_READ, MAP_SHARED, fd, 0) ;
if (ptrRecord == (char *)(caddr_t)(-1) ) {
perror("Fail to Map Data ");
return bSuccess;
}
else
{
printf("Successfully Map Data***[%ld] \n",sTotalSize);
bSuccess=true;
}
return bSuccess;
}
char * MapData::fnGetFileRef()
{
return ptrRecord;
}
char * MapData::ReadNextData(int iX)
{
if((lCurrRead+iX)<sTotalSize)
{
memset(acData,0x00,sizeof(acData));
strncpy(acData,ptrRecord+lCurrRead,iX);
acData[iX+1]='\0';
lCurrRead+=iX;
}else{
strcpy(acData,"ZZZ");
}
return acData;
}
long MapData::fnGetSize()
{
return sTotalSize;
}
void MapData::fnClose()
{
// Don't forget to free the mmapped memory
if(munmap(ptrRecord, sTotalSize) == -1)
{
close(fd);
perror("Error un-mmapping the file");
exit(EXIT_FAILURE);
}
// Un-mmaping doesn't close the file, so we still need to do that.
close(fd);
printf("CLOSED SUCCESSFULLY \n ");
}
Main.cpp
int main()
{
char acFileNm[500+1];
MEMSET(acFileNm); // clean the variable
// file name to be read
strcpy(acFileNm,"ABDFILE.txt");
long lProcCnt=0; // no of byte read by program
char acLine[MAX_LINE_LENGTH+1]; // hold current read line
bool bFlag=true; // main flag
DEBUG_PRINT("File to be processed:%s \n",acFileNm);
// create object of mmap
MapData * pt1 = NULL;
pt1 = new MapData(acFileNm);
if(!pt1)
{
cout<<"Error creating object so quit ..."<<endl;
return 0 ;
}
auto_ptr<MapData> ptrMap( pt1 ); // pass ownership to auto deletor to delete memory
DEBUG_PRINT("STEP1:%s \n","OBJECT CREATION FOR FILE MAPPED IN MEMORY");
// try to open the file
if(ptrMap->OPEN())
{
// on success..get pointer to first char of file
char * ptrData = ptrMap->fnGetFileRef();
long lCompSize=ptrMap->fnGetSize(); // total no of bytes = fiexed line size * no of row + (no of row * EOL)
short int iEOL=0;
// logic to identify file generated on ewhich OS
if( (*(ptrData+MAX_LINE_LENGTH) == '\r') && (*(ptrData+MAX_LINE_LENGTH+1) == '\n'))
{
// DOS format CRLF
iEOL = 2;
}else if(*(ptrData+MAX_LINE_LENGTH) == '\n'){
// Unix format LF
iEOL = 1;
}
DEBUG_PRINT("STEP2: SIZEOFFILE%ld FILESYSTEM FORMAT:%d \n",lCompSize,iEOL);
// here read till it reaches maximum limit of file
while(lProcCnt<lCompSize)
{
//DEBUG_PRINT("PROC COUNTER[%ld] MAX_COUNTER[%ld] \n",lProcCnt,lCompSize);
lProcCnt+=MAX_LINE_LENGTH+iEOL; // increement no of bytes read at initial
MEMSET(acLine);
strncpy(acLine,ptrData+lProcCnt,MAX_LINE_LENGTH); // read line
acLine[MAX_LINE_LENGTH+1]='\0';
// process the line :function is called here to process the line
}
}else{
DEBUG_PRINT("MAP DATA FAILED OF FILE[%s] \n",acFileNm);
bFlag=false;
}
// at the end check if all the controls are matched
if(bFlag)
DEBUG_PRINT("END OF FILE PROCESSING SUCCESS \n");
else
DEBUG_PRINT("END OF FILE PROCESSING FAILED \n");
// close the memory map
ptrMap->fnClose();
MapData * ptr5 = ptrMap.release(); // release the ownership
delete ptr5; **// segmentation fault comes here ...**
}
Please suggest me where i am going wrong since gdb is also not helping ...detailed explanation will be good for me to understand ...
Stacktrace generated by gdb:
*** glibc detected *** DemoMap: free(): invalid pointer: 0x0804c000 ***
======= Backtrace: =========
/lib/libc.so.6[0x9bbc81]
/lib/libc.so.6[0x9be562]
/usr/lib/libstdc++.so.6(_ZdlPv+0x22)[0x544552]
DemoMap[0x80491e6]
/lib/libc.so.6(__libc_start_main+0xe6)[0x961d36]
DemoMap[0x8048d91]
======= Memory map: ========
00110000-00111000 r-xp 00000000 00:00 0 [vdso]
0044c000-00469000 r-xp 00000000 08:03 1237 /lib/libgcc_s-4.4.7-20120601.so.1
00469000-0046a000 rw-p 0001d000 08:03 1237 /lib/libgcc_s-4.4.7-20120601.so.1
00495000-00576000 r-xp 00000000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
00576000-0057a000 r--p 000e0000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
0057a000-0057c000 rw-p 000e4000 08:02 132841 /usr/lib/libstdc++.so.6.0.13
0057c000-00582000 rw-p 00000000 00:00 0
00929000-00947000 r-xp 00000000 08:03 1065 /lib/ld-2.12.so
00947000-00948000 r--p 0001d000 08:03 1065 /lib/ld-2.12.so
00948000-00949000 rw-p 0001e000 08:03 1065 /lib/ld-2.12.so
0094b000-00adb000 r-xp 00000000 08:03 1067 /lib/libc-2.12.so
00adb000-00adc000 ---p 00190000 08:03 1067 /lib/libc-2.12.so
00adc000-00ade000 r--p 00190000 08:03 1067 /lib/libc-2.12.so
00ade000-00adf000 rw-p 00192000 08:03 1067 /lib/libc-2.12.so
00adf000-00ae2000 rw-p 00000000 00:00 0
00b29000-00b51000 r-xp 00000000 08:03 1211 /lib/libm-2.12.so
00b51000-00b52000 r--p 00027000 08:03 1211 /lib/libm-2.12.so
00b52000-00b53000 rw-p 00028000 08:03 1211 /lib/libm-2.12.so
08048000-0804b000 r-xp 00000000 08:08 2883976 DemoMap
0804b000-0804c000 rw-p 00002000 08:08 2883976 DemoMap
0804c000-0806d000 rw-p 00000000 00:00 0 [heap]
b7e00000-b7e21000 rw-p 00000000 00:00 0
b7e21000-b7f00000 ---p 00000000 00:00 0
b7f9b000-b7fe5000 r--s 00000000 08:08 4326707 ABCDEF.TXT
b7fe5000-b7fe8000 rw-p 00000000 00:00 0
b7ffd000-b8000000 rw-p 00000000 00:00 0
bffeb000-c0000000 rw-p 00000000 00:00 0 [stack]
may be here.
char ptrFileNm[250+1];
char acFileNm[500+1];
MapData::MapData(char acInput[])
{
strcpy(ptrFileNm,acInput);//segmentation fault
sTotalSize=0;
lCurrRead=0;
bSuccess=false;
}

SDL2/SDL_Image loading objcopy files

As stated on the topic, i'm using objcopy to load SDL_Image images with MinGW over Eclipse Helios for windows.
I'm using the command: objcopy --input-target binary --output-target pei-i386 --binary-architecture i386 Lilothyn.jpg Lilothyn.o
That results in the file:
Lilothyn.o: file format pei-i386
Lilothyn.o
architecture: i386, flags 0x00000030:
HAS_SYMS, HAS_LOCALS
start address 0x00000000
Characteristics 0x305
relocations stripped
line numbers stripped
32 bit words
debugging information removed
Time/Date Thu Jan 01 00:00:00 1970
Magic 0000
MajorLinkerVersion 0
MinorLinkerVersion 0
SizeOfCode 00000000
SizeOfInitializedData 00000000
SizeOfUninitializedData 00000000
AddressOfEntryPoint 00000000
BaseOfCode 00000000
BaseOfData 00000000
ImageBase 00000000
SectionAlignment 00000000
FileAlignment 00000000
MajorOSystemVersion 0
MinorOSystemVersion 0
MajorImageVersion 0
MinorImageVersion 0
MajorSubsystemVersion 0
MinorSubsystemVersion 0
Win32Version 00000000
SizeOfImage 00000000
SizeOfHeaders 00000000
CheckSum 00000000
Subsystem 00000000 (unspecified)
DllCharacteristics 00000000
SizeOfStackReserve 00000000
SizeOfStackCommit 00000000
SizeOfHeapReserve 00000000
SizeOfHeapCommit 00000000
LoaderFlags 00000000
NumberOfRvaAndSizes 00000000
The Data Directory
Entry 0 00000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 00000000 00000000 Import Directory [parts of .idata]
Entry 2 00000000 00000000 Resource Directory [.rsrc]
Entry 3 00000000 00000000 Exception Directory [.pdata]
Entry 4 00000000 00000000 Security Directory
Entry 5 00000000 00000000 Base Relocation Directory [.reloc]
Entry 6 00000000 00000000 Debug Directory
Entry 7 00000000 00000000 Description Directory
Entry 8 00000000 00000000 Special Directory
Entry 9 00000000 00000000 Thread Storage Directory [.tls]
Entry a 00000000 00000000 Load Configuration Directory
Entry b 00000000 00000000 Bound Import Directory
Entry c 00000000 00000000 Import Address Table Directory
Entry d 00000000 00000000 Delay Import Directory
Entry e 00000000 00000000 CLR Runtime Header
Entry f 00000000 00000000 Reserved
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 000024fb 00000000 00000000 000000c0 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _binary_Lilothyn_jpg_start
[ 1](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000024fb _binary_Lilothyn_jpg_end
[ 2](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000024fb _binary_Lilothyn_jpg_size
... and the other:
Tommy.o: file format pei-i386
Tommy.o
architecture: i386, flags 0x00000030:
HAS_SYMS, HAS_LOCALS
start address 0x00000000
Characteristics 0x305
relocations stripped
line numbers stripped
32 bit words
debugging information removed
Time/Date Thu Jan 01 00:00:00 1970
Magic 0000
MajorLinkerVersion 0
MinorLinkerVersion 0
SizeOfCode 00000000
SizeOfInitializedData 00000000
SizeOfUninitializedData 00000000
AddressOfEntryPoint 00000000
BaseOfCode 00000000
BaseOfData 00000000
ImageBase 00000000
SectionAlignment 00000000
FileAlignment 00000000
MajorOSystemVersion 0
MinorOSystemVersion 0
MajorImageVersion 0
MinorImageVersion 0
MajorSubsystemVersion 0
MinorSubsystemVersion 0
Win32Version 00000000
SizeOfImage 00000000
SizeOfHeaders 00000000
CheckSum 00000000
Subsystem 00000000 (unspecified)
DllCharacteristics 00000000
SizeOfStackReserve 00000000
SizeOfStackCommit 00000000
SizeOfHeapReserve 00000000
SizeOfHeapCommit 00000000
LoaderFlags 00000000
NumberOfRvaAndSizes 00000000
The Data Directory
Entry 0 00000000 00000000 Export Directory [.edata (or where ever we found it)]
Entry 1 00000000 00000000 Import Directory [parts of .idata]
Entry 2 00000000 00000000 Resource Directory [.rsrc]
Entry 3 00000000 00000000 Exception Directory [.pdata]
Entry 4 00000000 00000000 Security Directory
Entry 5 00000000 00000000 Base Relocation Directory [.reloc]
Entry 6 00000000 00000000 Debug Directory
Entry 7 00000000 00000000 Description Directory
Entry 8 00000000 00000000 Special Directory
Entry 9 00000000 00000000 Thread Storage Directory [.tls]
Entry a 00000000 00000000 Load Configuration Directory
Entry b 00000000 00000000 Bound Import Directory
Entry c 00000000 00000000 Import Address Table Directory
Entry d 00000000 00000000 Delay Import Directory
Entry e 00000000 00000000 CLR Runtime Header
Entry f 00000000 00000000 Reserved
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 000834fe 00000000 00000000 000000c0 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _binary_Tommy_jpg_start
[ 1](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000834fe _binary_Tommy_jpg_end
[ 2](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000834fe _binary_Tommy_jpg_size
The problem is that this last file (Tommy.o) loads properly, while the 1st file (Lilothyn.o) doesn't. As you can see the two are seemingly similar.
My code is extensive so i'll post the relevant parts only.
Source.cpp:
int displayFillThread(SDL_Renderer *renderer, SDL_Window *window, bool *_end) throw()
{
std::cout << "Thread initializing..." << std::endl;
SDL_Texture *texture = getTextureFromStream(&binary_Lilothyn_jpg_start, binary_Lilothyn_jpg_size, window, renderer);
if (texture == NULL)
{
std::cout << "Thread: Failed to load image - " << SDL_GetError() << std::endl;
return 1;
}
std::cout << "Thread initialized!" << std::endl;
for(int i= 10; !*_end && i < 400; i+= 100)
for(int j= 10; !*_end && j < 400; j+= 100)
{
SDL_Delay(100);
AddTextureToRederer(renderer, texture, i, j, 100, 100);
SDL_RenderPresent(renderer);
}
return 0;
}
SDL_Texture *getTextureFromStream(char binary[], unsigned int binary_size, SDL_Window *window, SDL_Renderer *renderer) throw()
{
std::cout << "Starting getTextureFromJPEGStream!" << std::endl;
// char* st = loadFileObject(binary_start, binary_end);
SDL_RWops *rw = SDL_RWFromConstMem(binary, binary_size);
std::cout << "rw loaded!" << std::endl;
SDL_Surface *tmpSurf = IMG_Load_RW(rw, 0);
//SDL_Surface *tmpSurf = SDL_CreateRGBSurfaceFrom(Lilothyn_jpg, 123, 102, 24, 96, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
if (tmpSurf != NULL)
{
SDL_Surface *surf = SDL_ConvertSurfaceFormat(tmpSurf, SDL_GetWindowPixelFormat(window), 0);
if (surf != NULL)
{
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surf);
SDL_FreeSurface(surf);
std::cout << "tmpSurf loaded!" << std::endl;
return texture;
}//*/
// SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, tmpSurf);
SDL_FreeSurface(tmpSurf);
std::cout << "surf load failed!" << std::endl;
return NULL;
}
std::cout << "tmpSurf load failed!" << std::endl;
return NULL;
}
int main(int argc, char** argv)
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
std::cout << "SDL init Error: " << SDL_GetError() << std::endl;
exit(1);
}
SDL_Window *window = SDL_CreateWindow("SDL_Test", 0, 0, _SCREEN_WIDTH_, _SCREEN_HEIGHT_, SDL_WINDOW_OPENGL | SDL_RENDERER_ACCELERATED); // SDL_WINDOW_FULLSCREEN |
if (window == NULL)
{
std::cout << "Window init Error: " << SDL_GetError() << std::endl;
exit(1);
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
if (renderer == NULL)
{
SDL_ShowSimpleMessageBox(0, "Renderer init error", SDL_GetError(), window);
}
//SDL_Texture *texture = getTextureFromJPEGStream(binary_Tommy_jpg_start, binary_Tommy_jpg_end, binary_Tommy_jpg_size, window, renderer);
SDL_Texture *texture = getTextureFromStream(&binary_Tommy_jpg_start, binary_Tommy_jpg_size, window, renderer);
//getTextureFromImage("Resources/Tommy.jpg", window, renderer);
if (texture == NULL)
{
SDL_ShowSimpleMessageBox(0, "Background Texture init error", SDL_GetError(), window);
return 1;
}
SDL_RenderCopy(renderer, texture, NULL, NULL);
//AddTextureToRederer(renderer, FTex, 10, 10, 100, 100);
SDL_RenderPresent(renderer);
SDL_Event event;
bool _end = false;
std::cout << "Starting Thread!" << std::endl;
std::thread thread1;
try
{
thread1 = std::thread(displayFillThread, renderer, window, &_end);
std::cout << "Thread loaded!" << std::endl;
}
catch(std::exception& e)
{
std::cout << "Thread load failed: " << e.what() << std::endl;
return 1;
}
std::cout << "main while starting!" << std::endl;
while(!_end)
{
//...
Source.h:
#ifndef SOURCE_H_
#define SOURCE_H_
static int _SCREEN_WIDTH_ = 1024;
static int _SCREEN_HEIGHT_ = 800;
extern char binary_Tommy_jpg_start;
extern unsigned int binary_Tommy_jpg_size;
extern char binary_Lilothyn_jpg_start;
extern unsigned int binary_Lilothyn_jpg_size;
int displayFillThread(SDL_Renderer *renderer, SDL_Window *window, bool *_end) throw();
SDL_Texture *getTextureFromStream(char binary[], unsigned int binary_size, SDL_Window *window, SDL_Renderer *renderer) throw();
//...
And the output:
Starting getTextureFromJPEGStream!
rw loaded!
tmpSurf loaded!
Starting Thread!
Thread loaded!
Thread initializing...
main while starting!
Note that it didn't write the second "getTextureFromJPEGStream!" neither did it appear to have thrown an exception.
It compiles with no problems whatsoever so, is it possible that the Lilothyn.o file is being created corrupted? (I have rebuilt it more than once) And/or maybe the linker isn't linking correctly?
While executing, the program simple stops responding after loading the 1st image, while trying to load the 2nd.
Thank you for the replies.
I've solved this now, the problem was the types used on the .o file.
New code is as follows.
Source.h:
extern uint8_t binary_Lilothyn_jpg_start[];
extern uint8_t binary_Lilothyn_jpg_size[];
Source.cpp
SDL_Texture *getTextureFromStream(uint8_t binary[], uint8_t binary_size[], SDL_Window *window, SDL_Renderer *renderer) throw()
{
size_t converted_size = (size_t)((void *)binary_size);
SDL_Surface *tmpSurf = IMG_Load_RW(SDL_RWFromConstMem(binary, converted_size), 0);
if (tmpSurf != NULL)
{
//...
Thanks to all the viewers, I hope this helps!

Stack Smashing Using Message Queues

i have the following main code:
#include "ComHandler.h"
#include "socketMessage.h"
#define THIS_IP "localhost"
#define C_PORT 32456
#define S_PORT 25465
#define S_PORT_UDP 22548
int main(int argc, char* argv[]) {
conOptions opts;
strncpy(opts.password, "PASS", sizeof("PASS"));
opts.retryQty = 5;
opts.timeout = 300;
char dir[INET6_ADDRSTRLEN];
strncpy(dir, THIS_IP, sizeof(THIS_IP));
if (argv[1][0] == 'C') {
opts.connType = CLIENT_HANDLER;
opts.thisID = 2;
ComHandler comH(opts);
char buffer[10];
strncpy(buffer, "Testing", 10);
int rtnValue = comH.sendMsg(buffer, 10, 1, TCP_C);
std::cout << "Returned Value: " << rtnValue << std::endl;
} else {
opts.connType = SERVER_HANDLER;
opts.thisID = 1;
ComHandler comH(opts);
comH.addConnectionData(2, dir, C_PORT);
comH.addConnectionData(comH.getID(), dir, S_PORT);
char rcvdTxt[MINIDATA_DATA_SIZE];
comH.receiveMsg(rcvdTxt, MINIDATA_DATA_SIZE, 2, TCP_C);
std::cout << "Received: " << rcvdTxt << std::endl;
comH.closeCommunications();
}
}
The code is for testing my communication platform. The platform works well, but the problem appears when the messages are received by the Handler (ComHandler). When i call the method "receiveMsg" from ComHandler, i get a "stack smashing detected" in the "return" of the method.
This is the "ComHandler" class:
#ifndef COMHANDLER_H_
#define COMHANDLER_H_
#include "Constants.h"
#include "ComConstants.h"
#include "DataLogger.h"
#include <list>
#include <math.h>
#define CLIENT_HANDLER 1
#define SERVER_HANDLER 2
#define COMMENT_LINE '#'
#define TXT_SEPARATOR ';'
#define MINIDATA_DATA_SIZE (COMDATA_MAX_SIZE - 4* sizeof(int))
enum CON_TYPE {
TCP_C, UDP_C
};
#pragma pack(push)
#pragma pack(1)
typedef struct {
int totalPackets;
int sequenceNumber;
int sequenceID;
int dataSize;
char data[MINIDATA_DATA_SIZE];
} miniData;
#pragma pack(pop)
typedef struct connectionOptions {
unsigned int timeout;
unsigned int retryQty;
id_t thisID;
char password[PASSWORD_MAX_SIZE];
int connType;
connectionOptions() :
timeout(CON_TIMEOUT), retryQty(SOCKET_RETRIES), connType(
SERVER_HANDLER) {
memset(password, 0, PASSWORD_MAX_SIZE);
}
connectionOptions(connectionOptions& opt) {
timeout = opt.timeout;
retryQty = opt.retryQty;
thisID = opt.thisID;
connType = opt.connType;
memcpy(password, opt.password, PASSWORD_MAX_SIZE);
}
} conOptions;
class ComHandler {
private:
int dataForwarder_ReceiverMsgQueue;
int dataForwarder_SenderMsgQueue;
conOptions opts;
int sequenceID;
Semaphore ch_mux;
SharedMemory<comHandlerGlOp> ch_shm;
void cpyMiniData(miniData* to, miniData* from);
void createIPCs();
public:
ComHandler();
ComHandler(conOptions options);
ComHandler(id_t thisID);
virtual ~ComHandler();
int receiveMsg(char* buffer, int bufferSize, id_t originID,
CON_TYPE type = TCP_C);
int sendMsg(char* buffer, std::size_t bufferSize, id_t destinationID,
CON_TYPE type = TCP_C);
void configListenersData(char addr[INET6_ADDRSTRLEN], int port,
CON_TYPE type);
void addConnectionData(id_t id, char addr[INET6_ADDRSTRLEN], int port);
void addConnectionData(const char* file);
void modifyConnectionData(id_t id, char addr[INET6_ADDRSTRLEN], int port);
void removeConnectionData(id_t id);
int getID();
void closeCommunications();
};
#endif /* COMHANDLER_H_ */
The comData structure:
typedef struct {
long type;
int requestType;
char destination[INET6_ADDRSTRLEN];
char origin[INET6_ADDRSTRLEN];
id_t originID;
id_t destinationID;
int port;
pid_t senderPid;
pid_t originPid;
char data[COMDATA_MAX_SIZE];
} comData;
And the method with the problem:
int ComHandler::receiveMsg(char* buffer, int bufferSize, id_t originID,
CON_TYPE type) {
comData aux;
aux.type = DATA_RECEIVE;
int qtyReceived = 0;
if (originID != ANY_MSG_ORIGIN) {
if (type == TCP_C)
aux.requestType = RECEIVE_DATA_FROM_DESTINATION_TCP;
else
aux.requestType = RECEIVE_DATA_FROM_DESTINATION_UDP;
} else {
if (type == TCP_C)
aux.requestType = RECEIVE_ANY_DATA_TCP;
else
aux.requestType = RECEIVE_ANY_DATA_UDP;
}
aux.originID = originID;
aux.senderPid = getpid();
aux.originPid = getpid();
msgsnd(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), 0);
msgrcv(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), getpid(), 0);
/* More Code */
return qtyReceived;
}
The stack smashing error appears after "return qtyReceived;" is called. And the /* More Code */ in the middle is the non important code, because if a delete that part, the stack smashing stills appears.
After much debugging i found that the smashing appears if i call:
`msgrcv(dataForwarder_ReceiverMsgQueue, &aux, sizeof(comData), getpid(), 0);`
if i comment that line, i don't get the error.
Also with the debugger, i was able to see that the messages from the queue arrive with good format and size, exactly as they should.
The console output is:
*** stack smashing detected ***: /media/blackhole/workspace/Final/bin/ComTest terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7df88d5]
/lib/i386-linux-gnu/libc.so.6(+0xe7887)[0xb7df8887]
/media/blackhole/workspace/Final/bin/ComTest[0x804dc6b]
/media/blackhole/workspace/Final/bin/ComTest[0x804a002]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb7d2a113]
/media/blackhole/workspace/Final/bin/ComTest[0x8049d11]
======= Memory map: ========
08048000-08054000 r-xp 00000000 08:05 256373 /media/blackhole/workspace/Final/bin/ComTest
08054000-08055000 r--p 0000b000 08:05 256373 /media/blackhole/workspace/Final/bin/ComTest
08055000-08056000 rw-p 0000c000 08:05 256373 /media/blackhole/workspace/Final/bin/ComTest
08056000-08077000 rw-p 00000000 00:00 0 [heap]
b7d0f000-b7d11000 rw-p 00000000 00:00 0
b7d11000-b7e87000 r-xp 00000000 08:06 525221 /lib/i386-linux-gnu/libc-2.13.so
b7e87000-b7e89000 r--p 00176000 08:06 525221 /lib/i386-linux-gnu/libc-2.13.so
b7e89000-b7e8a000 rw-p 00178000 08:06 525221 /lib/i386-linux-gnu/libc-2.13.so
b7e8a000-b7e8d000 rw-p 00000000 00:00 0
b7e8d000-b7ea9000 r-xp 00000000 08:06 525242 /lib/i386-linux-gnu/libgcc_s.so.1
b7ea9000-b7eaa000 r--p 0001b000 08:06 525242 /lib/i386-linux-gnu/libgcc_s.so.1
b7eaa000-b7eab000 rw-p 0001c000 08:06 525242 /lib/i386-linux-gnu/libgcc_s.so.1
b7eab000-b7eac000 rw-p 00000000 00:00 0
b7eac000-b7ed4000 r-xp 00000000 08:06 525251 /lib/i386-linux-gnu/libm-2.13.so
b7ed4000-b7ed5000 r--p 00028000 08:06 525251 /lib/i386-linux-gnu/libm-2.13.so
b7ed5000-b7ed6000 rw-p 00029000 08:06 525251 /lib/i386-linux-gnu/libm-2.13.so
b7ed6000-b7fb4000 r-xp 00000000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fb4000-b7fb5000 ---p 000de000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fb5000-b7fb9000 r--p 000de000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fb9000-b7fba000 rw-p 000e2000 08:06 5514 /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16
b7fba000-b7fc1000 rw-p 00000000 00:00 0
b7fdc000-b7fdd000 rw-s 00000000 00:04 163119127 /SYSV02056f32 (deleted)
b7fdd000-b7fdf000 rw-p 00000000 00:00 0
b7fdf000-b7fe0000 r-xp 00000000 00:00 0 [vdso]
b7fe0000-b7ffe000 r-xp 00000000 08:06 525208 /lib/i386-linux-gnu/ld-2.13.so
b7ffe000-b7fff000 r--p 0001d000 08:06 525208 /lib/i386-linux-gnu/ld-2.13.so
b7fff000-b8000000 rw-p 0001e000 08:06 525208 /lib/i386-linux-gnu/ld-2.13.so
bffdf000-c0000000 rw-p 00000000 00:00 0 [stack]
So, any ideas? If you need something about the code, just ask me.
According to this, the msgsz parameter of msgrcv() should be the size of the mtext member of the mymsg struct:
struct mymsg {
long int mtype; /* message type */
char mtext[1]; /* message text */
}
The problem is that you include the size of the mtype member (4 bytes) so msgrcv() writes four bytes past the end of your struct which trashes the stack.