One of my class has a trouble: its members data can change unexpectedly.
I have read similar subject on SO, and it seems to be apparent to an undefined behavior or a problem of pointer. But even with a very easy expression of my code, I still have it:
aid.cpp:
#include "aid.h"
bool AID::Detect(t_arr3d x, t_arr3d x_p1, t_arr3d x_p2, t_arr3d x_p3, t_arr3d x_p4, int fp) {
return false;
}
AID::AID() {
this->counter = 0;
maxErrorBound = 0.1;
maxErrorBound2 = 0.02; // = maxErrorBound * lambda
}
aid.h
#ifndef AID_H_
#define AID_H_
#include "detector.h"
#include "vec.h"
#include <map>
#include <vector>
#include <limits>
#include <cstddef>
#include <boost/assign/list_of.hpp>
#include <boost/unordered_map.hpp>
#include "constants.h"
using namespace rode;
using boost::assign::map_list_of;
using namespace std;
class AID: public Detector {
public:
bool Detect(t_arr3d x, t_arr3d x_p1, t_arr3d x_p2, t_arr3d x_p3, t_arr3d x_p4, int fp);
AID();
private:
int counter;
float maxErrorBound ;
float maxErrorBound2;
};
#endif
The class is called in another one (rode.cpp):
...
if(a_detector == "AID"){
AID d = AID( );
this->aid = &d;
}
...
With LLDB, I have put a watchpoint to check what is going on:
Watchpoint 1 hit:
old value: 0
new value: 1606405696
Process 38408 stopped
* thread #1: tid = 0x74cd2, 0x00007fff5fc12171 dyld`ImageLoaderMachO::findExportedSymbol(char const*, bool, ImageLoader const**) const + 13, queue = 'com.apple.main-thread', stop reason = watchpoint 1
frame #0: 0x00007fff5fc12171 dyld`ImageLoaderMachO::findExportedSymbol(char const*, bool, ImageLoader const**) const + 13
dyld`ImageLoaderMachO::findExportedSymbol:
-> 0x7fff5fc12171 <+13>: pushq %rax
0x7fff5fc12172 <+14>: movq %rcx, %r14
0x7fff5fc12175 <+17>: movl %edx, -0x2c(%rbp)
0x7fff5fc12178 <+20>: movq %rsi, %r15
(lldb) bt
* thread #1: tid = 0x74cd2, 0x00007fff5fc12171 dyld`ImageLoaderMachO::findExportedSymbol(char const*, bool, ImageLoader const**) const + 13, queue = 'com.apple.main-thread', stop reason = watchpoint 1
* frame #0: 0x00007fff5fc12171 dyld`ImageLoaderMachO::findExportedSymbol(char const*, bool, ImageLoader const**) const + 13
frame #1: 0x00007fff5fc184f6 dyld`ImageLoaderMachOCompressed::resolveTwolevel(ImageLoader::LinkContext const&, ImageLoader const*, bool, char const*, bool, ImageLoader const**) + 86
frame #2: 0x00007fff5fc18784 dyld`ImageLoaderMachOCompressed::resolve(ImageLoader::LinkContext const&, char const*, unsigned char, long, ImageLoader const**, ImageLoaderMachOCompressed::LastLookup*, bool) + 276
frame #3: 0x00007fff5fc1a09b dyld`ImageLoaderMachOCompressed::doBindFastLazySymbol(unsigned int, ImageLoader::LinkContext const&, void (*)(), void (*)()) + 235
frame #4: 0x00007fff5fc0424e dyld`dyld::fastBindLazySymbol(ImageLoader**, unsigned long) + 90
frame #5: 0x00007fff9610b3ba libdyld.dylib`dyld_stub_binder + 282
frame #6: 0x000000010004f268 wrf2sl`GCC_except_table678 + 3660
frame #7: 0x00000001000270f9 wrf2sl`main(argc=15, argv=0x00007fff5fbffaa0) + 21337 at wrf2sl.cc:170
frame #8: 0x00007fff9610d5c9 libdyld.dylib`start + 1
wrf2sl is my program. But the rest is not related to it.
Have you ever seen a similar trouble?
How should I check to understand what is going on?
The problem is here
if(a_detector == "AID"){
AID d = AID( );
this->aid = &d;
}
Here you create a local variable in the scope of the if body, and it's local only inside there. Then you store a pointer to that local variable, a pointer to an object that is destructed once the if statement is done. That will lead to undefined behavior when you try to dereference the pointer to a non-existent object.
My advice is to not use pointers to start with, and instead store the object as a value (i.e. an actual instance of the AID class). If you must use pointers, then allocate it dynamically with new, and remember to delete it when you're done with it (or optionally depending on use-case use a smart pointer).
Related
I want to create a 2D input vector for my machine learning model. The model runs on a ESP32 but I am running into issues when it comes to setting up such an vector.
I initialise a vector by std::vector<std::vector<float>> testing_vector;
and reserve memory in my setup routine by testing_vector.reserve(1000);
This works fine when I reserve for 1000 elements. When I reserve for over 4700 elements though,
my ESP crashes although ESP.getFreeHeap() and ESP.getMaxAllocHeap() shows me that there should be enough heap memory available.
Edit:
Thanks to the answers of "Some programmer dude" and "molbdnilo" below I realised that my calculations for required space first was wrong. When I reserve 4700 elements of 12Byte vector objects this would now result in 56.400 Bytes which is still under Max Alloc Heap of 110580 though.
Input
When I reserve memory for 4.700 elements by testing_vector.reserve(4700);the ESP crashes
Outcome
My serial monitor with enabled "ESP32 Exception Decoder" gives me:
Rebooting...
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
Total heap: 298076
Free heap: 274232
Total PSRAM: 0
Free PSRAM: 0
Max Alloc Heap: 110580
Max Vector Size: 357913941
abort() was called at PC 0x4013457b on core 1
Backtrace:0x400834e1:0x3ffb26900x40088c5d:0x3ffb26b0 0x4008d6b5:0x3ffb26d0 0x4013457b:0x3ffb2750 0x401345c2:0x3ffb2770 0x401346bb:0x3ffb2790 0x4013461a:0x3ffb27b0 0x400d1b16:0x3ffb27d0 0x400d1d95:0x3ffb27f0 0x40129fe7:0x3ffb2820
#0 0x400834e1:0x3ffb2690 in panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c:402
#1 0x40088c5d:0x3ffb26b0 in esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c:128
#2 0x4008d6b5:0x3ffb26d0 in abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c:46
#3 0x4013457b:0x3ffb2750 in __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:47
#4 0x401345c2:0x3ffb2770 in std::terminate() at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:57
#5 0x401346bb:0x3ffb2790 in __cxa_throw at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc:95
#6 0x4013461a:0x3ffb27b0 in operator new(unsigned int) at /builds/idf/crosstool-NG/.build/HOST-x86_64-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/new_op.cc:54
#7 0x400d1b16:0x3ffb27d0 in __gnu_cxx::new_allocator<std::vector<float, std::allocator<float> > >::allocate(unsigned int, void const*) at c:\users\d.fluhr\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\ext/new_allocator.h:111
(inlined by) std::allocator_traits<std::allocator<std::vector<float, std::allocator<float> > > >::allocate(std::allocator<std::vector<float, std::allocator<float> > >&, unsigned int) at c:\users\d.fluhr\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/alloc_traits.h:436
(inlined by) std::_Vector_base<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > >::_M_allocate(unsigned int) at c:\users\d.fluhr\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/stl_vector.h:296
(inlined by) std::vector<float, std::allocator<float> >* std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > >::_M_allocate_and_copy<std::move_iterator<std::vector<float, std::allocator<float> >*> >(unsigned int, std::move_iterator<std::vector<float, std::allocator<float> >*>, std::move_iterator<std::vector<float, std::allocator<float> >*>) at c:\users\d.fluhr\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/stl_vector.h:1398
(inlined by) std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > >::reserve(unsigned int) at c:\users\d.fluhr\.platformio\packages\toolchain-xtensa-esp32\xtensa-esp32-elf\include\c++\8.4.0\bits/vector.tcc:74
#8 0x400d1d95:0x3ffb27f0 in setup() at src/main.cc:104
#9 0x40129fe7:0x3ffb2820 in loopTask(void*) at C:/Users/d.fluhr/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:42
Conclusion
I don't understand this output very well but I understand the result is invoked by my "reserve" method.
But what could be the reason for this crash?
Code
unfortunately the tensorflow lib is very big. This is why I just present my main.cc here.
I reduced the main loop part but kept the setup part as it is for a better understanding whats going on in the background.
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/micro/system_setup.h"
#include "tensorflow/lite/schema/schema_generated.h"
// #include "main_functions.h"
#include "model.h"
#include "constants.h"
#include "output_handler.h"
// additional libraries by Daniel
#include "Arduino.h"
#include <chrono>
#include <iostream>
#include <vector>
#include "input_data.h"
//setting timer
using namespace std::chrono;
unsigned long interval = 2000;
auto t_0 = high_resolution_clock::from_time_t(0);
auto now = high_resolution_clock::now();
auto previousMillis = duration_cast<milliseconds>(now - t_0).count();
bool debug_flag = true;
// Globals, used for compatibility with Arduino-style sketches.
namespace {
const tflite::Model* model = nullptr;
tflite::MicroInterpreter* interpreter = nullptr;
TfLiteTensor* input = nullptr;
TfLiteTensor* output = nullptr;
int inference_count = 0;
// increase if esp spits out "Failed to resize buffer"
constexpr int kTensorArenaSize = 55000;
uint8_t tensor_arena[kTensorArenaSize];
} // namespace
// initialise test vector
std::vector<std::vector<float>> testing_vector;
// The name of this function is important for Arduino compatibility.
void setup() {
// Map the model into a usable data structure. This doesn't involve any
// copying or parsing, it's a very lightweight operation.
model = tflite::GetModel(g_model);
if (model->version() != TFLITE_SCHEMA_VERSION) {
MicroPrintf("Model provided is schema version %d not equal to supported "
"version %d.", model->version(), TFLITE_SCHEMA_VERSION);
return;
}
// This pulls in all the operation implementations we need.
// NOLINTNEXTLINE(runtime-global-variables)
static tflite::AllOpsResolver resolver;
// Build an interpreter to run the model with.
static tflite::MicroInterpreter static_interpreter(
model, resolver, tensor_arena, kTensorArenaSize);
interpreter = &static_interpreter;
// Allocate memory from the tensor_arena for the model's tensors.
TfLiteStatus allocate_status = interpreter->AllocateTensors();
if (allocate_status != kTfLiteOk) {
MicroPrintf("AllocateTensors() failed");
return;
}
// Obtain pointers to the model's input and output tensors.
input = interpreter->input(0);
output = interpreter->output(0);
// Keep track of how many inferences we have performed.
inference_count = 0;
//debugg information
std::cout << "Total heap: " << ESP.getHeapSize() << "\n";
std::cout << "Free heap: " << ESP.getFreeHeap() << "\n";
std::cout << "Total PSRAM: " << ESP.getPsramSize() << "\n";
std::cout << "Free PSRAM: " << ESP.getFreePsram() << "\n";
std::cout << "Max Alloc Heap: " << ESP.getMaxAllocHeap() << "\n";
std::cout << "Max Vector Size: " << testing_vector.max_size() << "\n";
// reserve memory for vector
testing_vector.reserve(4700);
}
// The name of this function is important for Arduino compatibility.
void loop() {
// setting up timer for test ouput
now = high_resolution_clock::now();
auto mseconds = duration_cast<milliseconds>(now - t_0).count();
if (mseconds- interval > previousMillis){
std::cout << "test ouput: I am in main loop";
previousMillis = duration_cast<milliseconds>(now - t_0).count();
}
}
Further Information:
I have a partition table and already played with configure different sizes
Partition Table
partition table image
Hardware
ESP32-S (NODEMCU-32)
SPI Flash 32Mbit
I connected esp32 WROOM-32D to web3 with this library.
https://github.com/kopanitsa/web3-arduino
I tested the eth_send example of that library with both Arduino Ide and Platformio
After connecting to the Wifi the exception is like that
[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
.Connected
abort() was called at PC 0x40162ff7 on core 1
Backtrace:0x40162ff7:0x3ffb23d00x4008cd21:0x3ffb23f0 0x40091ed1:0x3ffb2410 0x40162ff7:0x3ffb2490 0x4016303e:0x3ffb24b0 0x40154283:0x3ffb24d0 0x40153d92:0x3ffb24f0 0x40155275:0x3ffb2510 0x4015551d:0x3ffb2530 0x400dddef:0x3ffb2560 0x400de337:0x3ffb2580 0x400d293a:0x3ffb2610 0x400d2ada:0x3ffb27f0 0x400e0366:0x3ffb2820
I decoded the error exception with ESP exception Decoder and the error was decoded like this
Decoding stack results
0x400836f5: panic_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/panic.c line 402
0x4008cd21: esp_system_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_system/esp_system.c line 128
0x40091ed1: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/newlib/abort.c line 46
0x40162ff7: __cxxabiv1::__terminate(void (*)()) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc line 47
0x4016303e: std::terminate() at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_terminate.cc line 57
0x40154283: __cxxabiv1::__cxa_throw(void*, std::type_info*, void (*)(void*)) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/src/gcc/libstdc++-v3/libsupc++/eh_throw.cc line 95
0x40153d92: operator new(unsigned int) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/build/build-cc-gcc-final/xtensa-esp32-elf/no-rtti/libstdc++-v3/include/bits/exception.h line 63
0x40155275: std::__cxx11::basic_string , std::allocator >::_M_create(unsigned int&, unsigned int) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/build/build-cc-gcc-final/xtensa-esp32-elf/no-rtti/libstdc++-v3/include/ext/new_allocator.h line 99
0x4015551d: std::__cxx11::basic_string , std::allocator >::reserve(unsigned int) at /builds/idf/crosstool-NG/.build/HOST-i686-w64-mingw32/xtensa-esp32-elf/build/build-cc-gcc-final/xtensa-esp32-elf/no-rtti/libstdc++-v3/include/bits/basic_string.h line 189
0x400dddef: std::operator+ , std::allocator >(char const*, std::__cxx11::basic_string , std::allocator > const&) at c:\users\yanna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\bits/char_traits.h line 287
0x400de337: Web3::EthGetTransactionCount(std::__cxx11::basic_string , std::allocator > const*) (C:\Program Files at x86)\Arduino\libraries\web3-arduino\src\Web3.cpp line 137
0x400d293a: eth_send_example() at C:\Users\yanna\Documents\Arduino\basic_web3\eth_send/eth_send.ino line 53
0x400d2ada: setup() at C:\Users\yanna\Documents\Arduino\basic_web3\eth_send/eth_send.ino line 43
0x400e0366: loopTask(void*) at C:\Users\yanna\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.4\cores\esp32\main.cpp line 42
This is my codes
#include <WiFi.h>
#include <Web3.h>
#include <Contract.h>
#define USE_SERIAL Serial
const char* ssid = "V1A7C";
const char* password = /*<password>*/;
#define MY_ADDRESS "0x1b9aE0Be6d87e79b9Bd5A6FcDc67d92F76F6e0F6"
#define CONTRACT_ADDRESS "0xDA832c3825A37d693d17D9360d5289B8B2b580f0"
#define INFURA_HOST "eth-rinkeby.alchemyapi.io"
#define INFURA_PATH "/v2/1yNgxbZKvL4JzOIjnNUywYue0ruh_Fjt"
const char PRIVATE_KEY[] = {/*<32 bytes of private key>*/};
Web3 web3((string*)INFURA_HOST, (string*)INFURA_PATH);
void eth_send_example();
void setup() {
USE_SERIAL.begin(115200);
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
USE_SERIAL.println("Connected");
eth_send_example();
}
void loop() {
// put your main code here, to run repeatedly:
}
void eth_send_example() {
Contract contract(&web3,(string*) CONTRACT_ADDRESS);
contract.SetPrivateKey((uint8_t*)PRIVATE_KEY);
uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount((string *)MY_ADDRESS);
uint32_t gasPriceVal = 141006540;
uint32_t gasLimitVal = 3000000;
uint8_t toStr[] = CONTRACT_ADDRESS;
uint8_t valueStr[] = "0x00";
uint8_t dataStr[100];
memset(dataStr, 0, 100);
string func = "mint(uint256)";
string p = contract.SetupContractData(&func, 123);
string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, (string*) &toStr,(string*) &valueStr,(string*) &p);
Serial.println(result);
}
You are casting C char pointers to std::string pointers like this.
#define MY_ADDRESS "..."
...
uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount((string *)MY_ADDRESS);
Don't do that. If you need a pointer to a string, you should create an instance of the string like this.
string address = MY_ADDRESS;
uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(&address);
As a side note, I don't recommend to use the web3-arduino.(I am very certain that the author of that library is a novice on C++.)
I'm new to libtorch and I need to load a LSTM network in C++. Before that, I have already tested with the following Python script and it is working well:
actuator_net_file = "resources/actuator_nets/anydrive_v3_lstm.pt"
actuator_network = torch.jit.load(actuator_net_file)
actuator_network.eval()
num_envs = 1
num_actions = 1
sea_input = torch.zeros(num_envs*num_actions, 1, 2, requires_grad=False)
sea_hidden_state = torch.zeros(2, num_envs*num_actions, 8, requires_grad=False)
sea_cell_state = torch.zeros(2, num_envs*num_actions, 8, requires_grad=False)
torques, (sea_hidden_state[:], sea_cell_state[:]) = actuator_network(sea_input, (sea_hidden_state, sea_cell_state))
And the next step is to write a simple C++ program to test the forward evaluation of the network. But I don't know how to give arguments to the forward function. Here is what I got:
#include <torch/script.h> // One-stop header.
#include <torch/torch.h>
#include <iostream>
#include <memory>
#include <vector>
int main(int argc, const char* argv[]) {
if (argc != 2) {
std::cerr << "usage: example-app <path-to-exported-script-module>\n";
return -1;
}
std::string actuator_net_file = "/home/fenglongsong/Desktop/example-app/anydrive_v3_lstm.pt";
torch::jit::script::Module actuator_network;
try {
actuator_network = torch::jit::load(actuator_net_file);
actuator_network.eval();
}
catch (const c10::Error& e) {
std::cerr << "error loading the model\n";
return -1;
}
std::cout << "load model ok\n";
const int num_envs = 1;
const int num_actions = 1;
auto u0 = torch::zeros({num_envs*num_actions, 1, 2});
auto h0 = torch::zeros({2, num_envs*num_actions, 8});
auto c0 = torch::zeros({2, num_envs*num_actions, 8});
std::vector<torch::jit::IValue> inputs;
inputs.push_back(u0);
std::vector<torch::jit::IValue> tuple;
tuple.push_back(h0);
tuple.push_back(c0);
inputs.push_back(c10::ivalue::Tuple::create(tuple));
std::cout << "before forward" << std::endl;
actuator_network.forward(inputs).toTensor();
}
The compile passes successfully but when running the executable, the following error occurs:
fenglongsong#alvaro-rsl ~/Desktop/example-app/build $ ./example-app .
load model ok
before forward
terminate called after throwing an instance of 'c10::Error'
what(): Expected Tensor but got Tuple
Exception raised from reportToTensorTypeError at ../aten/src/ATen/core/ivalue.cpp:908 (most recent call first):
frame #0: c10::Error::Error(c10::SourceLocation, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) + 0x6b (0x7f9153dc07ab in /home/fenglongsong/Documents/ocs2_ws/src/libtorch/lib/libc10.so)
frame #1: c10::detail::torchCheckFail(char const*, char const*, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) + 0xce (0x7f9153dbc15e in /home/fenglongsong/Documents/ocs2_ws/src/libtorch/lib/libc10.so)
frame #2: c10::IValue::reportToTensorTypeError() const + 0x64 (0x7f913dd6d304 in /home/fenglongsong/Documents/ocs2_ws/src/libtorch/lib/libtorch_cpu.so)
frame #3: c10::IValue::toTensor() && + 0x4b (0x55d1ce3cd311 in ./example-app)
frame #4: main + 0x54e (0x55d1ce3ca0ec in ./example-app)
frame #5: __libc_start_main + 0xf3 (0x7f913c7c6083 in /lib/x86_64-linux-gnu/libc.so.6)
frame #6: _start + 0x2e (0x55d1ce3c986e in ./example-app)
Aborted (core dumped)
My question is, what should be the equivalence in C++ of
torques, (sea_hidden_state[:], sea_cell_state[:]) = actuator_network(sea_input, (sea_hidden_state, sea_cell_state)) ? Any suggessions will be much appreciated!
I have experience only directly with torch::Tensor, not with torch::jit::IValue, but generally, the signature is:
network.forward(const Tensor & input, torch::optional<std::tuple<Tensor,Tensor>>)
So in your example, you would call it like this:
actuator_network.forward(u0, std::make_tuple(h0, c0)).toTensor();
But it depends on the actual architecture, next time, include the actuator network architecture to your question to make it more clear.
I am trying to create a user space stack and run functions using this stack.
Following are the steps I am doing.
Allocate a space for the stack.
Before calling a function, switch the stack pointer to the new location.
Also try to store previous or original stack pointer
Return of the called function
Restore the original stack pointer
I implemented the following based on the above points:
/* Ubuntu 18.04 x86_64 */
/* Compiler gcc version 7.5.0 */
#include <iostream>
#include <cassert>
#include <memory>
class Thread {
public:
/* stack will point to lowest addr of th User Stack */
unsigned char * stack = nullptr;
/*stack_ptr will point to the Highest addr of the User Stack */
unsigned char* stack_ptr = nullptr;
int stack_size = 0;
Thread() {
stack_size = 16*64; // 1024 B
stack = new unsigned char[stack_size];
/*stack_ptr points to the highest memory of this space*/
stack_ptr = stack + stack_size;
}
~Thread() {
std::cout <<"User stack deleted"<< std::endl;
if(stack != nullptr)
delete[] stack;
}
void func(int x,int y) {
std::cout <<"Hello from the func ["<<x<<"] ["<<y<<"]"<< std::endl;
}
};
int main() {
/* createa a User level Thread */
Thread t;
/* Some random local variable */
// int a[100];
unsigned char* stk = t.stack_ptr;
/* Note: rsp = current stack top */
uint64_t prev_stack = 0; /* for assert checking */
uint64_t x = 7; /*some random value, just for stack alighment of 16B */
asm("movq %%rsp, %%r11\n\t" /* save current stack ptr to r11(or rax etc.) */
"movq %%r11, %[out1]\n\t" /* just for assert check later */
"movq %[in1], %%rsp\n\t" /* change rsp to stk, i.e. to our own stack top */
"pushq %%r11\n\t" /* Push r11 or prev stack ptr to current stack */
"pushq %[in2]\n\t" /* for stack alignment only */
:[out1] "=m" (prev_stack) /*just for assert check later */
:[in1] "m" (stk),[in2] "m" (x) /* two inputs */
:);
// call the func, this func
// will will use our own stack
t.func(1,2);
/*just for checking x */
uint64_t y;
uint64_t _prev_stack;
asm(
"popq %[out1]\n\t" /* y = stack.pop() */
"popq %%rsp\n\t" /* restore stack: rsp = stack.pop() */
"movq %%rsp, %[out2]\n\t" /* just for checking */
:[out1] "=m" (y),[out2] "=m" (_prev_stack) /* two outputs */
:
:
);
assert(prev_stack == _prev_stack && "Main's stack not restored!");
std::cout <<std::hex<<"Stack restored = "<< prev_stack << std::endl;
assert(x == y && "x and y are not equal!!");
std::cout <<"Program Ended!" << std::endl;
}
I have added couple of extra checks, just for debug purpose.
The following output is generated:
Hello from the func [1] [2]
Stack restored = 7ffd55eb8ea0
Program Ended!
User stack deleted
munmap_chunk(): invalid pointer
[1] 27337 abort (core dumped) ./a.out
It seems that, I can safely (?) return to the original function, because the instruction pointer is restored automatically (due to callq and retq operation sequence, gcc compiler did this) and the program also gets back the original rsp or the stack top. The rbp pointer is also taken care of by the compiler.
But I get an error in the destructor of the Thread class.
I tried to debug on my own using gdb, but I could not find any reason for observed the error:
Here are the output of the gdb backtrace
_GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
>>> bt
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00001555545f2801 in __GI_abort () at abort.c:79
#2 0x000015555463b897 in __libc_message (action=action#entry=do_abort, fmt=fmt#entry=0x155554768b9a "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3 0x000015555464290a in malloc_printerr (str=str#entry=0x15555476a7a8 "munmap_chunk(): invalid pointer") at malloc.c:5350
#4 0x0000155554649ecc in munmap_chunk (p=0x614e60) at malloc.c:2846
#5 __GI___libc_free (mem=0x614e70) at malloc.c:3117
#6 0x0000000000400e2d in Thread::~Thread() ()
#7 0x0000000000400bdc in main ()
However valgrind shows no leaks.
==27982== HEAP SUMMARY:
==27982== in use at exit: 0 bytes in 0 blocks
==27982== total heap usage: 3 allocs, 3 frees, 74,752 bytes allocated
==27982==
==27982== All heap blocks were freed -- no leaks are possible
(Although valgrind warns : Warning: client switching stacks?, I think it is normal w.r.t to the above code)
Observation: If I comment out the if(stack != nullptr) delete[] stack line, error goes out
but valgrind shows the following:
=28019== 1,024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28019== at 0x4C3089F: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28019== by 0x108ED7: Thread::Thread() (test.cpp:20)
==28019== by 0x108BBD: main (test.cpp:36)
I am really confused with the memory free error and no leak status. What could be the cause of such memory deallocation error ? Am I doing any mistake while saving and restoring old and new stacks ?
Thanks.
Update
I simplified the code:
/* Ubuntu 18.04 x86_64 */
/* Compiler gcc version 7.5.0 */
#include <iostream>
#include <cassert>
#include <memory>
const int _stack_size = 16*64; // 1024B
void func(int x,int y) {
std::cout <<"Hello from the func ["<<x<<"] ["<<y<<"]"<< std::endl;
}
int main() {
unsigned char * stackBase = new unsigned char[_stack_size];
unsigned char * stackTop = stackBase + _stack_size;
std::cout <<"Before "<<std::hex <<(void*)(stackBase) << std::endl;
asm volatile("movq %%rsp, %%r11\n\t" /* save current stack ptr to r11(or rax etc.) */
"movq %[in1], %%r12\n\t"
"movq %%r12, %%rsp\n\t" /* change rsp to stk, i.e. to our own stack top */
"pushq %%r11\n\t" /* Push r11 or prev stack ptr to current stack */
// "pushq %%rbp\n\t"
: /*no input */
:[in1] "m" (stackTop) /* two inputs */
:"r11","r12","rsp");
func(1,2);
asm volatile(
"popq %%rsp\n\t" /* restore stack: rsp = stack.pop() */
:/* no outputs */
:/* no inputs */
:"rsp");
std::cout <<"Program Ended!" << std::endl;
std::cout <<"After "<<std::hex<<(void*)(stackBase) << std::endl;
delete[] stackBase;
}
But it still shows the double free error:
Before 0x555e80926e70
Hello from the func [1] [2]
Program Ended!
After 0x555e80926e70
double free or corruption (out)
[1] 4343 abort (core dumped) ./a.out
Error in runtine with -fsanitize=address option:
Before 0x619000000080
ASAN:DEADLYSIGNAL
=================================================================
==5605==ERROR: AddressSanitizer: stack-overflow on address 0x618ffffffb90 (pc 0x14b656131576 bp 0x619000000418 sp 0x618ffffffb98 T0)
#0 0x14b656131575 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x51575)
#1 0x14b655e39039 in std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (/usr/local/gcc-10/lib64/libstdc++.so.6+0x12c039)
#2 0x564202743e4b in func(int, int) (/home/deka/Academic/userLevelThread/a.out+0x2e4b)
#3 0x5642027445ca in main (/home/deka/Academic/userLevelThread/a.out+0x35ca)
#4 0x14b654c1cb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#5 0x564202743d49 in _start (/home/deka/Academic/userLevelThread/a.out+0x2d49)
SUMMARY: AddressSanitizer: stack-overflow (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x51575)
==5605==ABORTING
I meet a strange behavior for a c++11 program, and can not figure out what is going wrong. please gave me some advises. thanks.
basically, it is a OpenCL program.
struct memory_layout
{
public:
memory_layout(managed_device d);
scalar<int> s;
};
memory_layout::memory_layout(managed_device d) :
s(d)
{
}
class doer
{
public:
doer();
void go();
private:
managed_device dev;
memory_layout mem;
};
doer::doer():
dev(find_CPU()),
mem(dev)
{
}
void doer::go()
{
task t = copy(10,mem.s);
}
int main(){
doer d;
d.go();
return 0;
}
when it runs to copy function, it has "Segmentation Fault".
Here is the def of copy:
template <typename T>
task copy(const T& source, scalar<T>& sink, const std::vector<task>& deps = {} )
{
return sink.device().create_task( profile::copy<T>(source, sink), deps );
}
When I use gdb to debug:
Breakpoint 1, doer::go (this=0x7fffffffdc90) at main.cpp:79
79 task t = copy(10,mem.s); // device() original be 0x60f0d0
(gdb) p mem.s.device()
$1 = (cppcl::opencl_1_2::device::managed_device &) #0x7fffffffdc60: {_device = 0x60f0d0}
(gdb) s
std::vector<unsigned long, std::allocator<unsigned long> >::vector (this=0x7fffffffdc50) at /usr/include/c++/4.8.3/bits/stl_vector.h:249
249 : _Base() { }
(gdb)
std::_Vector_base<unsigned long, std::allocator<unsigned long> >::_Vector_base (this=0x7fffffffdc50)
at /usr/include/c++/4.8.3/bits/stl_vector.h:125
125 : _M_impl() { }
(gdb)
std::_Vector_base<unsigned long, std::allocator<unsigned long> >::_Vector_impl::_Vector_impl (this=0x7fffffffdc50)
at /usr/include/c++/4.8.3/bits/stl_vector.h:87
87 : _Tp_alloc_type(), _M_start(0), _M_finish(0), _M_end_of_storage(0)
(gdb)
std::allocator<unsigned long>::allocator (this=0x7fffffffdc50) at /usr/include/c++/4.8.3/bits/allocator.h:113
113 allocator() throw() { }
(gdb)
__gnu_cxx::new_allocator<unsigned long>::new_allocator (this=0x7fffffffdc50) at /usr/include/c++/4.8.3/ext/new_allocator.h:80
warning: Source file is more recent than executable.
80
(gdb)
std::_Vector_base<unsigned long, std::allocator<unsigned long> >::_Vector_impl::_Vector_impl (this=0x7fffffffdc50)
at /usr/include/c++/4.8.3/bits/stl_vector.h:88
88 { }
(gdb)
cppcl::opencl_1_2::device::copy<int> (source=#0x7fffffffdc6c: 10, sink=..., deps=std::vector of length 0, capacity 0)
at /usr/include/cppcl/1.2/device/buffer_templates.h:1233
warning: Source file is more recent than executable.
1233 return sink.device().create_task( profile::copy<T>(source, sink), deps );
(gdb) p sink.device()
$2 = (cppcl::opencl_1_2::device::managed_device &) #0x7fffffffdc60: {_device = 0x0}
after I step into the copy function, it first build the "deps" parameter, and then, the _device value changed to 0x0. I could not figure out why this happy?
thanks for giving me some suggestions.
I'm assuming that you're not asking what's wrong with your code, that you're only asking how to figure out yourself what's wrong with your code. Otherwise, there's not enough information in your question.
This is a good first step in debugging. You've found clear indication that one value in memory is being changed. You've found a concrete object managed_device at address 0x7fffffffdc60 that contains a value that gets changed somehow.
Let me use a simple complete program:
#include <stdio.h>
int *p;
void f() {
++*p;
}
int main() {
int i = 3;
p = &i;
printf("%d\n", i); // i is 3 here.
f();
printf("%d\n", i); // Huh? i is 4 here.
}
Now, of course it is completely and utterly obvious why i changes in this program, but let's suppose that I completely overlooked it anyway.
If I set a breakpoint on line 13 (the call to f), and inspect i, I see that it is still 3.
Breakpoint 1, main () at test.cc:13
13 f();
(gdb) p i
$1 = 3
No surprise there. And I've already determined that the value will at some unknown point in the future get changed, I just don't know when.
I can now use the watch instruction to monitor that variable for changes:
(gdb) watch i
Hardware watchpoint 2: i
and then continue execution:
(gdb) cont
Continuing.
Hardware watchpoint 2: i
Old value = 3
New value = 4
f () at test.cc:7
7 }
(gdb) bt
#0 f () at test.cc:7
#1 0x004011e9 in main () at test.cc:13
Now, I have seen that the code that modified i was just before the closing brace in f.
This is what you'll need to do with your own code. It'll be a bit more complex than in this simple example, but you should be able to use it for your own code as well.