I'm using nanomsg for request/receive and the code I have works just fine when I compiled it using a Makefile. However when I try using cmake, it compiles just fine but runs into Segmentation Fault when trying to send a message.
Does anyone know what's going on? I'm also unsure if the issue is in my cmake file or in the .cc files.
Here is a minimal working example.
request.cc (its .h file is omitted here)
Requester::Requester(const char* url) {
int socket = nn_socket(AF_SP, NN_REQ);
assert(socket >= 0);
assert(nn_connect (socket, url) >= 0);
}
Requester::~Requester() {
nn_shutdown(socket, 0);
}
const char* Requester::request_for_sentence(const char* sentence){
int size_sentence = strlen(sentence) + 1;
int bytes = nn_send(socket, sentence, size_sentence, 0); # segmentation fault occurs here
assert(bytes == size_sentence);
char *buf = NULL;
bytes = nn_recv(socket, &buf, NN_MSG, 0);
assert(bytes >= 0);
printf("REQUESTER RECEIVED %s\n", buf);
return buf;
}
request_test.cc
int main(int argc, char** argv) {
extractor::Requester my_requester("ipc:///tmp/extractor.ipc");
const char* output = my_requester.request_for_sentence("some input");
cerr << "output: " << output << endl;
return 0;
}
receiver.cc
int main(int argc, char** argv) {
const char* url = "ipc:///tmp/extractor.ipc";
int socket = nn_socket (AF_SP, NN_REP);
assert(socket >= 0);
assert(nn_bind (socket, url) >= 0);
while(1){
char *buf = NULL;
int bytes = nn_recv(socket, &buf, NN_MSG, 0);
assert (bytes >= 0);
const char* grammar_for_sentence = extract_for_sentence(buf);
cerr << grammar_for_sentence << endl;
int size_grammar = strlen(grammar_for_sentence) + 1; // '\0' too
bytes = nn_send(socket, grammar_for_sentence, size_grammar, 0);
assert(bytes == size_grammar);
nn_freemsg (buf);
}
return 0;
}
Makefile that works:
CC=g++
CFLAGS = -L$HOME/opt/lib -I$HOME/opt/include -lnanomsg
all : run_test run_extract_daemon
run_test : extract_request_test.cc extract_request.o
$(CC) $(CFLAGS) -o run_test extract_request_test.cc extract_request.o -I.
run_extract_daemon : extract_daemon.cc
$(CC) $(CFLAGS) -o run_extract_daemon extract_daemon.cc
extract_request.o : extract_request.cc extract_request.h
$(CC) $(CFLAGS) -c extract_request.cc
clean :
rm run_test run_extract_daemon extract_request.o
CMakeLists.txt that doesn't work:
find_package(nanomsg)
if(NANOMSG_FOUND)
include_directories(${NANOMSG_INCLUDE_DIR})
set(extract_request_test_SRCS extract_request_test.cc)
add_executable(run_extractor_request_test ${extract_request_test_SRCS})
target_link_libraries(run_extractor_request_test extractor ${NANOMSG_LIBRARIES})
set(extract_daemon_SRCS extract_daemon.cc)
add_executable(run_daemon ${extract_daemon_SRCS})
target_link_libraries(run_daemon extractor ${NANOMSG_LIBRARIES})
endif(NANOMSG_FOUND)
set(extractor_STAT_SRCS
extract_request.cc
extract_request.h)
add_library(extractor STATIC ${extractor_STAT_SRCS})
Related
I'm tring to use program ***to print frame stack *** in C/C++ code.
Below is a demo find form internet:
print call stack in C or C++
#include <cassert>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <iomanip>
#include <cxxabi.h> // __cxa_demangle
#include <elfutils/libdwfl.h> // Dwfl*
#include <execinfo.h> // backtrace
#include <unistd.h> // getpid
using namespace std;
// https://stackoverflow.com/questions/281818/unmangling-the-result-of-stdtype-infoname
std::string demangle(const char* name) {
int status = -4;
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
std::string debug_info(Dwfl* dwfl, void* ip) {
uintptr_t ip2 = reinterpret_cast<uintptr_t>(ip);
Dwfl_Module* module = dwfl_addrmodule(dwfl, ip2);
char const* name = dwfl_module_addrname(module, ip2);
std::string function_name = name ? demangle(name) : "<unknown>";
int line_num = -1;
char const* file_name;
if (Dwfl_Line* dwfl_line = dwfl_module_getsrc(module, ip2)) {
Dwarf_Addr addr;
file_name = dwfl_lineinfo(dwfl_line, &addr, &line_num, nullptr, nullptr, nullptr);
}
std::stringstream ss;
ss << std::setw(16)<<std::setfill('0') <<ip << ' ' << function_name;
if (file_name)
ss << " at " << file_name << ':' << line_num;
ss << std::endl;
return ss.str();
}
std::string gen_framestack_backtrace() {
// Initialize Dwfl.
Dwfl* dwfl = nullptr;
{
Dwfl_Callbacks callbacks = {};
char* debuginfo_path = nullptr;
callbacks.find_elf = dwfl_linux_proc_find_elf;
callbacks.find_debuginfo = dwfl_standard_find_debuginfo;
callbacks.debuginfo_path = &debuginfo_path;
dwfl = dwfl_begin(&callbacks);
assert(dwfl);
int r;
r = dwfl_linux_proc_report(dwfl, getpid());
assert(!r);
r = dwfl_report_end(dwfl, nullptr, nullptr);
assert(!r);
static_cast<void>(r);
}
// Loop over stack frames.
std::stringstream ss;
{
void* stack[512];
int stack_size = ::backtrace(stack, sizeof stack / sizeof *stack);
for (int i = 0; i < stack_size; ++i) {
ss << i << ": ";
// Works.
ss << debug_info(dwfl, stack[i]);
#if 0
// TODO intended to do the same as above, but segfaults,
// so possibly UB In above function that does not blow up by chance?
void *ip = stack[i];
std::string function;
int line = -1;
char const* file;
uintptr_t ip2 = reinterpret_cast<uintptr_t>(ip);
Dwfl_Module* module = dwfl_addrmodule(dwfl, ip2);
char const* name = dwfl_module_addrname(module, ip2);
function = name ? demangle(name) : "<unknown>";
// TODO if I comment out this line it does not blow up anymore.
if (Dwfl_Line* dwfl_line = dwfl_module_getsrc(module, ip2)) {
Dwarf_Addr addr;
file = dwfl_lineinfo(dwfl_line, &addr, &line, nullptr, nullptr, nullptr);
}
ss << ip << ' ' << function;
if (file)
ss << " at " << file << ':' << line;
ss << std::endl;
#endif
}
}
dwfl_end(dwfl);
return ss.str();
}
void my_func_2() {
std::cout << gen_framestack_backtrace() << std::endl;
std::cout.flush();
}
void my_func_1(double f) {
(void)f;
my_func_2();
}
void my_func_1(int i) {
(void)i;
my_func_2();
}
int main(int argc, char **argv) {
long long unsigned int n;
if (argc > 1) {
n = strtoul(argv[1], NULL, 0);
} else {
n = 1;
}
for (long long unsigned int i = 0; i < n; ++i) {
my_func_1(1); // line 122
my_func_1(2.0); // line 123
}
}
Run:
$ sudo apt install libdw-dev libunwind-dev
$
$ g++ -fno-pie -ggdb3 -O0 -no-pie -o a.out -std=c++11 -Wall -Wextra -pedantic-errors test.cpp -ldw -lunwind -ggdb
$ ./a.out
Result:
0: 000000000x401ab1 stacktrace[abi:cxx11]() at /home/wxq/test/test7.cpp:71
1: 000000000x401c11 my_func_2() at /home/wxq/test/test7.cpp:106
2: 000000000x401ca2 my_func_1(int) at /home/wxq/test/test7.cpp:117
3: 000000000x401d01 main at /home/wxq/test/test7.cpp:128
4: 000x7f3e4ee4dbf6 __libc_start_main at ../csu/libc-start.c:310
5: 000000000x401479 _start at ../csu/libc-start.c:-1
0: 000000000x401ab1 stacktrace[abi:cxx11]() at /home/wxq/test/test7.cpp:71
1: 000000000x401c11 my_func_2() at /home/wxq/test/test7.cpp:106
2: 000000000x401c8f my_func_1(double) at /home/wxq/test/test7.cpp:112
3: 000000000x401d16 main at /home/wxq/test/test7.cpp:129
4: 000x7f3e4ee4dbf6 __libc_start_main at ../csu/libc-start.c:310
5: 000000000x401479 _start at ../csu/libc-start.c:-1
But above solution can not print function arguments
Does any one have solution to print backtrace in C/C++ program, just like gdb bt command?
Just like below command
#0 createObj1 (handle=0x5555559291c0, shimHandle=0x55555595a850) at /home/wxq/setup.cpp:983
#1 0x00007ffff60a3763 in initialize (this=0x55555595a850, config=...)at /home/wxq/test.cpp:197
#2 0x00007ffff60a24f2 in create_extended (setup=0x5555559291c0) at /home/wxq/test.cpp:509
#3 0x0000555555555538 in main (argc=5, argv=0x7fffffffe0e8) at /home/wxq/core_model.cpp:145
Using the following code, why do I get different hash values?
#include <iostream>
#include <cstring>
#include <openssl/evp.h>
# define SHA256_DIGEST_LENGTH 32
using namespace std;
static void hex_print(const char *name, const unsigned char *buf, size_t len)
{
size_t i;
fprintf(stdout, "%s ", name);
for (i = 0; i < len; i++)
fprintf(stdout, "%02X", buf[i]);
fputs("\n", stdout);
}
int main (int argc, char *argv[])
{
EVP_MD_CTX *ctx;
//const EVP_MD *evp_md = EVP_sha256();
char *msg = (char*)"I have the high ground...";
unsigned int msg_size = strlen(msg);
unsigned char digest_a[SHA256_DIGEST_LENGTH] = {0};
unsigned char digest_b[SHA256_DIGEST_LENGTH] = {0};
cout << "message: " << msg << endl;
cout << "length: " << msg_size << endl;
ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
EVP_DigestUpdate(ctx, msg, msg_size);
EVP_DigestFinal_ex(ctx, digest_a, &msg_size);
hex_print("sha256: ", digest_a, SHA256_DIGEST_LENGTH);
EVP_Digest (msg, msg_size, digest_b, NULL, EVP_sha256 (), NULL);
hex_print ("sha256: ", digest_b, SHA256_DIGEST_LENGTH);
EVP_MD_CTX_free(ctx);
return EXIT_SUCCESS;
}
Compiled on Ubuntu 20.04 LTS using gcc
g++ -Wall -g -o test test.cpp -I/usr/include/openssl -L/usr/lib/x86_64-linux-gnu l:libcrypto.so
Output:
message: I have the high ground...
length: 25
sha256: 2873FC569EFBE61AC67A1247CCBAE0AE94BE97D227D1ECEF3C9E93A8EA3CAD33
sha256: F13852B3A521A6D08169AAA42525AA63FEF87D8A22418A25A8E19F3FD15E750D
When I paste the string into an online tool such as https://emn178.github.io/online-tools/sha256.html, the "correct" hash seems to be the first one:
2873fc569efbe61ac67a1247ccbae0ae94be97d227d1ecef3c9e93a8ea3cad33
Can anyone explain me why this is happening? Thanks!
The call EVP_DigestFinal_ex(ctx, digest_a, &msg_size) overwrites msg_size to SHA256_DIGEST_LENGTH, which is not equal to the original 25.
You then go on to use msg_size as if it was still the original value.
I haven't ever used ffmpeg on my own laptop. All's ok at work, but here I met an ugly problem: library works but helpless:)
Ubuntu 18.04, ffmpeg 4.1 (downloaded sources, ./configure, make, sudo make install), it seems to be ok.
Application returns:
File /home/ahlininv/Desktop/video_example.mp4 is encodec with '' codec, w = 0, h = 0
I ran it under debugger. If I set format to zero, pointer changes after calling avformat_open_input(&format, file, 0, &dict), so it works and maybe works correct.
Maybe it plays any role that compiler says that av_register_all, avcodec_register_all are deprecated, but I thought it's not significant problem.
I tried to change version of ffmpeg (tried to install it with apt-get, version 3.somenumber is available), nothing changed.
I tried to run another video file (.avi), nothing changed, too.
Guys, help=) How to this file's info correctly?
main.cpp:
#include "filereader.h"
int main(int argc, char** argv) {
std::string filename = "/home/ahlininv/Desktop/video_example.mp4";
std::string codec;
int w, h;
bool open_ok = get_file_info(filename.c_str(), codec, w, h);
if (!open_ok) {
std::cout << "Failed to open file" << "\n";
return 1;
}
std::cout << "File " << filename << " is encoded with '" << codec << "' codec, w = " << w << ", h = " << h << "\n";
return 0;
}
filereader.h:
#ifndef FILEREADER_H
#define FILEREADER_H
#include <string>
#include <iostream>
extern "C" {
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include "libavcodec/avcodec.h"
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}
bool get_file_info(const char* file, std::string& codec, int& w, int& h);
#endif // FILEREADER_H
filereader.cpp
#include "filereader.h"
bool get_file_info(const char* file, std::string& codec, int& w, int& h)
{
codec = "";
w = h = 0;
av_register_all();
avcodec_register_all();
AVDictionary* dict = 0;
AVFormatContext* format = avformat_alloc_context();
char errbuf[256];
int r = avformat_open_input(&format, file, 0, &dict);
if (r!=0){
av_strerror(r, errbuf, sizeof(errbuf));
std::cout << "avformat_open_input error: " << errbuf << "\n";
}
if (r == AVERROR(EIO) || r == AVERROR(ENOEXEC) || !format)
return false;
for (size_t c = 0; c < format->nb_streams; ++c)
{
if (format->streams[c]->codecpar && format->streams[c]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
if (format->streams[c]->codecpar->codec_id != AV_CODEC_ID_NONE &&
format->streams[c]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO)
{
w = format->streams[c]->codecpar->width;
h = format->streams[c]->codecpar->height;
codec = avcodec_get_name(format->streams[c]->codecpar->codec_id);
}
}
}
avformat_close_input(&format);
return true;
}
Compile:
g++ -o filereader main.cpp filereader.cpp -lavutil -lavformat -lavcodec -lavdevice -lz -lm -pthread -lswresample -lm -lz -I /usr/local/include/ -Wl,-rpath /usr/lib/x86_64-linux-gnu/
Can you add these lines Before for loop on filereader.cpp to see if it makes any difference.
if (avformat_find_stream_info(format, NULL) < 0)
{
//handle error
}
here is my code:
int fd[2];
pipe(fd);
fd[0];
fd[1];
std::string cmd = "valgrind --leak-check=yes --track-origins=yes --xml=yes --xml-fd=";
cmd += std::to_string(fd[1]);
cmd += " /tmp/home/roroco/Dropbox/rbs/ro_cmds_global/c/valgrind/ex/ex2";
system(cmd.c_str());
close(fd[1]);
int n = 1024;
char buffer[1024];
std::string r;
while (read(fd[0], buffer, n) != 0) {
r += buffer;
}
std::cout << r << std::endl;
the executable "ex2" code is:
int *is;
is[2] = 2;
return (0);
here is output, I get messy code like <\360\034#
update
when i use --xml-file, it output normal text like this
I find the solution, it's because int n = 1024 istoo slow, following code will work:
int main(int argc, char **argv) {
int fd[2];
pipe(fd);
fd[0];
fd[1];
std::string cmd = "valgrind --leak-check=yes --track-origins=yes --xml=yes --xml-fd=";
cmd += std::to_string(fd[1]);
cmd += " /tmp/home/roroco/Dropbox/rbs/ro_cmds_global/c/valgrind/ex/ex2";
system(cmd.c_str());
close(fd[1]);
int n = 4096;
char buffer[n];
std::string r;
while (read(fd[0], buffer, n) != 0) {
r += buffer;
}
close(fd[0]);
std::cout << r << std::endl;
return (0);
}
but I don't know why it's 4096? why it's not 2048, 1024, how to determine this value? if someone know, please change this answer
I have the following simple program involving pthread and semaphore. I am in osx Maverck 10.9. I use a makefile to compile the program (rather than xcode). I use c++11.
#include <pthread.h>
#include <semaphore.h>
#include <cassert>
#include <iostream>
#define ASSERT(a) if(!(a)) abort
using namespace std;
sem_t countMutex;
int myCount=0;
void *doThread(void *data) {
int *pi = reinterpret_cast<int *>(data);
sem_wait(&countMutex);
for(int i =0 ;i < 100; ++i) {
myCount += 1;
}
sem_post(&countMutex);
pthread_exit( NULL );
}
void LaunchThread() {
const int kNumThreads = 10;
pthread_t tids[kNumThreads];
int threadData[kNumThreads];
pthread_attr_t attr;
pthread_t tid;
int retVal=0;
retVal = pthread_attr_init(&attr);
ASSERT(retVal == 0);
retVal = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE );
ASSERT(retVal == 0);
sem_init(&countMutex, 0, 1);
myCount = 0;
for(int i=0; i < kNumThreads; ++i) {
threadData[i] = i;
retVal = pthread_create( &tids[i], &attr, &doThread, &threadData[i]);
if(retVal != 0) {
cerr << "cannot create thread" << endl;
return;
}
}
retVal = pthread_attr_destroy(&attr);
ASSERT(retVal == 0);
void *status = NULL;
for(int i=0; i < kNumThreads; ++i) {
retVal = pthread_join( tids[i], &status);
if(retVal != 0) {
cerr << "cannot join ghread " << i << ", " << tids[i] << endl;
return;
}
cout << "completed thread " << i << ", " << tids[i] << endl;
}
cout << "value of myCount: " << myCount << endl;
sem_destroy(&countMutex);
//sem_unlink(&countMutex);
pthread_exit( NULL );
}
int main( int argc, char **argv) {
LaunchThread();
return 0;
}
The makefile for compiling this is
CXX=clang++
CXXFLAGS=-g -Wall -Wno-deprecated -std=c++11 -pthread -D DEBUG -g3 $(INCLUDES)
LDFLAGS=$(LIBS)
OBJS=main.o
PROG=test
all: $(PROG)
$(PROG): $(OBJS)
$(CXX) -v -o $(PROG) main.o $(LDFLAGS)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $<
clean:
rm $(OBJS); rm test
The program ought to have reported a value of 1000 for myCount. But is inconsistent, on multiple runs.
Eg:
completed thread 0, 0x107dca000
completed thread 1, 0x107e4d000
completed thread 2, 0x107ed0000
completed thread 3, 0x107f53000
completed thread 4, 0x107fd6000
completed thread 5, 0x108059000
completed thread 6, 0x1080dc000
completed thread 7, 0x10815f000
completed thread 8, 0x1081e2000
completed thread 9, 0x108265000
value of myCount: 900
Unnamed POSIX semaphores are not supported on OSX. If you check your return codes you will see sem_init fail with an error along those lines. You need to use named semaphores.
Use sem_open instead of sem_init. Don't use sem_destroy but rather sem_close and sem_unlink.
You will be good to go.