Try to use placement new but it kept giving me errors. I remember a while ago, it was working. g++ (ver 4.8.4) on Ubuntu 14.04.
#include <stdio.h>
typedef unsigned int uint;
struct strSession {
uint sessionId;
uint srcIp;
uint dstIp;
};
int main(int argc, char *argv[]) {
char buf[20];
strSession *q = (strSession*)&buf[0];
new (q) strSession;
return 0;
}
Got error
$ g++ -std=c++11 te.cc `pkg-config --cflags glib-2.0`
te.cc: In function ‘int main(int, char**)’:
te.cc:12:10: error: no matching function for call to ‘operator new(sizetype, strSession*&)’
new (q) strSession;
^
te.cc:12:10: note: candidate is:
<built-in>:0:0: note: void* operator new(long unsigned int)
<built-in>:0:0: note: candidate expects 1 argument, 2 provided
Any idea what's wrong?
To use placement new, you need to have:
#include <new>
Also, you could just as easily have used:
int main(int argc, char *argv[]) {
char buf[20];
strSession *q = new (buf) strSession;
return 0;
}
To make your original code work, you need to add
void* operator new( size_t, strSession * p ) { return p; }
In the old days, before C++ left Bell Labs, C++ had a feature where
a constructor could assign to 'this'. The operator new placement
syntax was considered an improvement.
Related
I want to use std::compare_exchange_strong for some std::atomic<int>
For compilation reasons (int &) I am forced to introduce int _OLD_VALUE = OLD_VALUE.
Is there a more elegant way to achieve this?
Here is my example
#include <atomic>
#include <stdio.h>
#define OLD_VALUE 16
#define NEW_VALUE 744
#define OTHER_VALUE 80
int main(int argc, char **argv)
{
std::atomic<int> i(OTHER_VALUE);
int _OLD_VALUE = OLD_VALUE;
bool status = i.compare_exchange_strong(_OLD_VALUE,NEW_VALUE);
// bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
}
And here is the compilation error when I use the commented version:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:11:65: error: cannot bind non-const lvalue reference of type ‘std::__atomic_base<int>::__int_type& {aka int&}’ to an rvalue of type ‘int’
bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
^
In file included from /usr/include/c++/7/atomic:41:0,
from main.cpp:1:
/usr/include/c++/7/bits/atomic_base.h:496:7: note: initializing argument 1 of ‘bool std::__atomic_base<_IntTp>::compare_exchange_strong(std::__atomic_base<_IntTp>::__int_type&, std::__atomic_base<_IntTp>::__int_type, std::memory_order) [with _ITp = int; std::__atomic_base<_IntTp>::__int_type = int; std::memory_order = std::memory_order]’
compare_exchange_strong(__int_type& __i1, __int_type __i2,
^~~~~~~~~~~~~~~~~~~~~~~
No. The reason being is that the previous value of the variable is exchanged so the expected value is overwritten if the compare mismatches.
To see what's going on under the hood, look at the GCC built-ins:
https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
You will note there is a __atomic_exchange_n in the builtins for GCC (Linux) but that simply provides an exchange as opposed to a compare-and-swap. The Windows equivalent is InterlockedExchange : https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-interlockedexchange
For the sake of readability I would avoid using capitals in variable names and avoid leading underscores:
int oldValue = OLD_VALUE;
The simplest way (and I suppose the only way) to achieve this is to just write simple wrapper:
bool cas_strong(std::atomic<int>& a, int cmp, int exc) {
return a.compare_exchange_strong(cmp, exc);
}
compare_exchange_strong expects an int& to store the current value found in i. Here, you provide indirectly 16 (that is what your macro OLD_VALUE is replaced with at pre-processing), which is an integer compile-time constant, a.k.a. constexpr int&. This is not compatible with int&.
To provide an int&, you should better keep an int near your call of compare_exchange_strong:
std::atomic<int> i(OTHER_VALUE);
int old_value = OLD_VALUE;
bool status = i.compare_exchange_strong(old_value, NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
Also, more generally, it is clearly more powerful if you used static constants instead of macros here.
More on this in this other question: What is the difference between a macro and a const in C++?
Don't use macros to define the values:
#include <atomic>
#include <stdio.h>
int OLD_VALUE 16
int NEW_VALUE 744
int OTHER_VALUE 80
int main(int argc, char **argv)
{
std::atomic<int> i(OTHER_VALUE);
bool status = i.compare_exchange_strong( OLD_VALUE,NEW_VALUE);
if (status) { printf("good\n"); }
return 0;
}
I want to override open from libc using LD_PRELOAD:
#include <dlfcn.h>
#include <sys/stat.h>
extern "C" {
int open(const char *path, int flags, mode_t mode)
{
int (*originalOpen)(const char *path, int flags, mode_t mode);
originalOpen = reinterpret_cast<decltype(originalOpen)>(dlsym(RTLD_NEXT, "open"));
//originalOpen = reinterpret_cast<decltype(open)>(dlsym(RTLD_NEXT, "open"));
//...
return (*originalOpen)(path, flags, mode);
}
}
I compile with g++ -fPIC -shared -o open.so open.cpp -ldl.
Can somebody tell me why the above code works, and why I get the errror:
error: invalid cast from type ‘void*’ to type ‘int(const char*, int, mode_t)’ {aka ‘int(const char*, int, unsigned int)’}
originalOpen = reinterpret_cast<decltype(open)>(dlsym(RTLD_NEXT, "open"));
when I initialize originalOpen with the line commented out?
I used gcc version 8.0.1.
Try this code:
originalOpen = reinterpret_cast<decltype(open) *>(dlsym(RTLD_NEXT, "open"));
Decltype gets the type of the function while You want to create function pointer. There is implicit cast from function to pointer of its type but these are not equivalent. This is why version with decltype(original_open) works perfectly - type of original_open is function pointer and not the function.
I'm having difficulty figuring out exactly how to use execvp in C++. I'm not having any issues getting my code to work, but I'm specifically trying to figure out how to do it in a way that doesn't make the compiler complain.
I have looked at various questions on Stack Overflow and other resources, but I have been unable to find a solution that results in zero warnings from the compiler.
Consider the following C++ program, which prints its own source code:
#include <unistd.h>
int main(int argc, char *argv[])
{
char *args[3];
args[0] = "/bin/cat";
args[1] = __FILE__;
args[2] = NULL;
execvp(args[0], args);
return 0;
}
(I know that the return 0 should never be reached; I'm not so concerned with error handling in this question.)
When I compile it, the compiler emits two warnings:
$ g++ -Wall exec.cpp
exec.cpp: In function ‘int main(int, char**)’:
exec.cpp:6:15: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
args[0] = "/bin/cat";
^~~~~~~~~~
exec.cpp:7:15: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
args[1] = __FILE__;
^~~~~~~~
The compiled program successfully prints the source file. However, I'd really like to get the program to compile without any warnings. Since the compiler doesn't like that the string literals are being assigned to a pointer of type char* (not const char*), I suppose it would make sense to mark args as an array of const char* pointers. Consider this version of the program:
#include <unistd.h>
int main(int argc, char *argv[])
{
const char *args[3];
args[0] = "/bin/cat";
args[1] = __FILE__;
args[2] = NULL;
execvp(args[0], args);
return 0;
}
I would think that this program should compile and run with no warnings or errors, but the compiler does emit an error:
$ g++ -Wall exec.cpp
exec.cpp: In function ‘int main(int, char**)’:
exec.cpp:10:25: error: invalid conversion from ‘const char**’ to ‘char* const*’ [-fpermissive]
execvp(args[0], args);
^
In file included from exec.cpp:1:0:
/usr/include/unistd.h:581:12: note: initializing argument 2 of ‘int execvp(const char*, char* const*)’
extern int execvp (const char *__file, char *const __argv[])
^~~~~~
I also tried declaring args as char const *args[3], but the compiler emits the same error. The only way I am able to get it to compile with no warnings is by casting args in the call to execvp:
const char *args[3];
...
execvp(args[0], (char* const*)args);
This version compiles without warnings and runs successfully. However, I prefer to avoid casting when I can, because it makes it harder for me to reason about the type conversions going on.
Are one of the two working ways that I have shown above the best way to create an argument array to pass to execvp, or is there a better way that is clear and does not result in the compiler complaining?
I am using two different compilers - g++ 6.2.0 for native compilation on Ubuntu x86_64, and g++ 4.5.3 for cross compilation to an ARM platform.
Edit:
I do not believe that my question is a duplicate of this question. I understand the different effects of using const in different ways with respect to a char* variable. I am specifically asking which type is conventionally used for execvp calls, which is not answered by the linked question.
The below code works perfectly with strings but with char it gives segmentation fault.
#include<iostream>
using namespace std;
class salary
{
public:
int empno;
float inctax;
float netsal;
int gross;
short int age;
char name[50];
salary(){
empno=0;
gross=0;
age=0;
strcpy(name,'\0');
}
salary(int empn,int gros,short int ag,char nam[]){
empno=empn;
gross=gros;
age=ag;
strcpy(name,nam);
}
void calc(){
inctax=0.0;
if(gross>1000000)
inctax=0.3*gross;
else if(gross>=500000 && gross<=1000000)
inctax=0.2*gross;
else if(gross>=250000 && gross<500000)
inctax=0.1*gross;
else
inctax=0.0;
netsal=gross-inctax;
cout<<"inctax"<<inctax;
cout<<"net sal"<<netsal;
}
};
int main(){
salary *r=new salary();
salary *r1=new salary(112,500000,21,"Arnab");
r1->calc();
return 0;
}
I agree with vu1p3n0x's comment,
the problem is in the default constructor.
strcpy(name, '\0'); // This is wrong!
strcpy() takes two char arrays as arguments, but a character itself was passed as the second argument in your code.
The syntax of strcpy() is:
char * strcpy ( char * destination, const char * source );
In order to create null string using char arrays, you should probably use,
strcpy(name, "\0");
/*or*/
name[0] = '\0';
More on copying string, Reference and tutorialspoint
Your main problem is that your compiler isn't telling you about the obvious errors in the code. If you have correctly told it to report errors, then you perhaps need a better compiler. Here's the output I get when I compile:
g++ -std=c++14 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses 38113648.cpp -o 38113648
38113648.cpp: In constructor ‘salary::salary()’:
38113648.cpp:18:25: error: ‘strcpy’ was not declared in this scope
strcpy(name,'\0');
^
38113648.cpp: In constructor ‘salary::salary(int, int, short int, char*)’:
38113648.cpp:25:24: error: ‘strcpy’ was not declared in this scope
strcpy(name,nam);
^
38113648.cpp: In function ‘int main()’:
38113648.cpp:46:48: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
salary *r1=new salary(112,500000,21,"Arnab");
^
38113648.cpp:45:13: warning: unused variable ‘r’ [-Wunused-variable]
salary *r=new salary();
^
When I add
#include <cstring>
and change the constructor to take char const[], I get
g++ -std=c++14 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses 38113648.cpp -o 38113648
38113648.cpp: In constructor ‘salary::salary()’:
38113648.cpp:19:25: warning: null argument where non-null required (argument 2) [-Wnonnull]
strcpy(name,'\0');
^
Obviously you meant that to be "\0". Better still, provide an initializer:
salary()
: empno{0},
gross{0},
age{0},
name{0}
{
}
salary(int empno, int gross, short int age, char const name[])
: empno{empno},
gross{gross},
age{age}
{
strcpy(this->name, name);
}
(I've also given the formal parameters more meaningful names, as this often forms the documentation of the constructor).
Adding -Weffc++ may also be worthwhile - in this case it warns that you don't initialize inctax or netsal in the constructors. If you're happy to have part-initialized objects, you'll obviously need to use Valgrind to check that these values are indeed set before they are used, because it can't be determined statically.
My question is related to this thread.
Here is the code
#include <stdio.h>
int main(int argc, char *argv[printf("Hello, world!\n")]) {}
I accidently saved it as a *.cpp file and tried to compile it with g++. But I got an error and a warning.
error: expected ',' or '...' before 'argv'
warning: second argument of 'int main(int, char*)' should be 'char **
'
I know the above code is not Standard C++ [size of an array must be a constant expression in C++] but
I always thought g++ supports Varible Length Array as an extension. Where am I wrong?
P.S : The above code gets compiled with CLang++
C:\Users\SUPER USER\Desktop>type check.cpp
#include <stdio.h>
int main(int argc, char *argv[printf("Hello, world!\n")]) {}
C:\Users\SUPER USER\Desktop>clang++ check.cpp
C:\Users\SUPER USER\Desktop>
g++ allows (again, as an extension) VLAs. I think it just doesn't allow them in parameter lists. This compiles in g++ 4.4.1.
#include <stdio.h>
int main(int argc, char *argv[])
{
char *array[printf("Hello, world!\n")];
}