What is equivalent mmap into C++?
I have code like below
LCDdata = mmap(NULL, iFrameBufferSize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fb_fd, 0);
Where LCDdata is unsigned char type pointer, iFrameBufferSize is int type and fb_fd is static int type.
When I compile it by use of arm g++ tool chain it give me error as below
error: invalid conversion from 'void*' to 'unsigned char*' [-fpermissive]
So how can I use any equivalent type function instead of mmap?
Which header file I should include? And how this new line's syntax will become?
The C++ equivalent is auto LCDdata = static_cast<unsigned char*>(mmap(...
In C++ we prefer to define out variables only when we initialize them, and because of that we often don't need to specify the type anymore. Here, we don't need to repeat unsigned char*.
C allows void* to be assigned to pointers of any type without a cast. C++ does not. C programmers have complained about this for ages (malloc being the most common complaint), but it's not likely to change.
The solution is to add the cast. If the source needs to be compilable as C, use a C-style cast:
LCDdata = (unsigned char*)mmap(...);
Otherwise use a C++ cast
LCDdata = static_cast<unsigned char*>(mmap(...));
If you want to do something more drastic, you could look into Boost Interprocess. That would give you RAII.
Related
Im trying to get rid of a platform dependent code.
This code gets a string formated by a mask ("%Y-%m-%d %H:%M:%S") and convert it to std::tm struct and a std::time seconds.
I want to get rid of the need of preprocessor dependant blocks, as (imho) there must be a standard way of doing it in both platforms in the same way.
strptime does not exists in windows, std::get_time does not exists(?) on linux (g++ c++11).
Is there any way to make this code crossplatform (windows/linux) without using a factory pattern or preprocessor dependant blocks?
KDATETIME& KDATETIME::operator= (const char* k)
{
std::string smask;
smask = (std::string)this->mask;
std::string sk;
sk=k;
tm.tm_isdst=-1;
#ifdef WINDOWS <<---- THIS BLOCK
std::istringstream ss(sk);
ss >> std::get_time(&tm, smask.c_str());
#else
strptime(sk.c_str(), smask.c_str(), &tm);
#endif <<------
this->time = mktime(&tm); // t is now your desired time_t
[...]
}
I am working in a legacy codebase with a large amount of Objective-C++ written using manual retain/release. Memory is managed using lots of C++ std::shared_ptr<NSMyCoolObjectiveCPointer>, with a suitable deleter passed in on construction that calls release on the contained object. This seems to work great; however, when enabling UBSan, it complains about misaligned pointers, usually when dereferencing the shared_ptrs to do some work.
I've searched for clues and/or solutions, but it's difficult to find technical discussion of the ins and outs of Objective-C object pointers, and even more difficult to find any discussion about Objective-C++, so here I am.
Here is a full Objective-C++ program that demonstrates my problem. When I run this on my Macbook with UBSan, I get a misaligned pointer issue in shared_ptr::operator*:
#import <Foundation/Foundation.h>
#import <memory>
class DateImpl {
public:
DateImpl(NSDate* date) : _date{[date retain], [](NSDate* date) { [date release]; }} {}
NSString* description() const { return [&*_date description]; }
private:
std::shared_ptr<NSDate> _date;
};
int main(int argc, const char * argv[]) {
#autoreleasepool {
DateImpl date{[NSDate distantPast]};
NSLog(#"%#", date.description());
return 0;
}
}
I get this in the call to DateImpl::description:
runtime error: reference binding to misaligned address 0xe2b7fda734fc266f for type 'std::__1::shared_ptr<NSDate>::element_type' (aka 'NSDate'), which requires 8 byte alignment
0xe2b7fda734fc266f: note: pointer points here
<memory cannot be printed>
I suspect that there is something awry with the usage of &* to "cast" the shared_ptr<NSDate> to an NSDate*. I think I could probably work around this issue by using .get() on the shared_ptr instead, but I am genuinely curious about what is going on. Thanks for any feedback or hints!
There were some red herrings here: shared_ptr, manual retain/release, etc. But I ended up discovering that even this very simple code (with ARC enabled) causes the ubsan hit:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSDate& d = *[NSDate distantPast];
NSLog(#"%#", &d);
}
return 0;
}
It seems to simply be an issue with [NSDate distantPast] (and, incidentally, [NSDate distantFuture], but not, for instance, [NSDate date]). I conclude that these must be singleton objects allocated sketchily/misaligned-ly somewhere in the depths of Foundation, and when you dereference them it causes a misaligned pointer read.
(Note it does not happen when the code is simply NSLog(#"%#", &*[NSDate distantPast]). I assume this is because the compiler simply collapses &* on a raw pointer into a no-op. It doesn't for the shared_ptr case in the original question because shared_ptr overloads operator*. Given this, I believe there is no easy way to make this happen in pure Objective-C, since you can't separate the & operation from the * operation, like you can when C++ references are involved [by storing the temporary result of * in an NSDate&].)
You are not supposed to ever use a "bare" NSDate type. Objective-C objects should always be used with a pointer-to-object type (e.g. NSDate *), and you are never supposed to get the "type behind the pointer".
In particular, on 64-bit platforms, Objective-C object pointers can sometimes not be valid pointers, but rather be "tagged pointers" which store the "value" of the object in certain bits of the pointer, rather than as an actual allocated object. You must always let the Objective-C runtime machinery deal with Objective-C object pointers. Dereferencing it as a regular C/C++ pointer can lead to undefined behavior.
There is an union in C and embedded into C++ as below:
typedef union MyUnion MyUnion_;
union MyUnion{
ULONG mLong;
char mChar;
...
};
When I trying to init it like:
MyUnion_ test;
test = (MyUnion_)NULL;
this is can compile by Mingw32, but gives
error: C2440: 'type cast': cannot convert from 'void *' to 'MyUnion_'
in VC++ (VS2015). So how to do cast & initialize of union in VC++ compiler?
Now I am doing like this:
MyUnion_ test;
test.mLong = NULL;
but this makes the program look bad when passing union as a parameter.
void test(MyUnion_ u)
ULONG i = 0;
// mingw32
test((MyUnion_)i);
// vc++
MyUnion_ temp;
temp.mLong = i;
test(temp);
Using a compiler that supports the C++11 uniform initialization syntax you can use a braced initializer with a single value which will be used to initialize the first non-static field of the union …
MyUnion test{ 0 };
You could use NULL instead of zero in the code above but it seems confusing to initialise mLong (which is a ULONG) with NULL.
You can also use braced initialization in an assignment statement if you have to set the variable after it was declared …
MyUnion test{ 0 };
// ...
test = { 3 };
Note that the braced initializer syntax may also be available in older compilers that offer experimental support for what used to be called C++0x
Visual Studio 2015 C++ supports braced initializers unless you are compiling a file with a .c extension or are using the /TC switch to compile as C code (rather than C++ code).
Older C++ (and C) compilers
When using compilers that don't support braced initialization the older assignment initialization syntax can be used in declarations ...
MyUnion_ test = { 0 };
… but not in assignment statements.
Casting to union type
According to this IBM Knowledge Center article casting to a union type is an extension to C99 "... implemented to facilitate porting programs developed with GNU C" - which suggests it's not standard C.
This Microsoft documentation indicates there are no legal casts in C for a union, struct or array.
In C++ a cast to a union type is possible if a suitable constructor exists...
union MyUnion {
unsigned long mLong;
char mChar;
MyUnion(unsigned long val) { mLong = val; };
};
// valid cast
test = (MyUnion)3ul;
// invalid cast - no suitable constructor exists
void * ptr = 0;
test = (MyUnion)ptr;
Default constructor?
typedef union MyUnion MyUnion_;
union MyUnion {
ULONG mLong;
char mChar;
MyUnion(): mLong(0) {}
};
int main()
{
MyUnion_ temp;
return 0;
}
BYTE name[1000];
In my visual c++ project there is a variable defined name with the BYTE data type. If i am not wrong then BYTE is equivalent to unsigned char. Now i want to convert this unsigned char * to LPCTSTR.
How should i do that?
LPCTSTR is defined as either char const* or wchar_t const* based on whether UNICODE is defined or not.
If UNICODE is defined, then you need to convert the multi-byte string to a wide-char string using MultiByteToWideChar.
If UNICODE is not defined, a simple cast will suffice: static_cast< char const* >( name ).
This assumes that name is a null-terminated c-string, in which case defining it BYTE would make no sense. You should use CHAR or TCHAR, based on how are you operating on name.
You can also assign 'name' variable to CString object directly like:
CString strName = name;
And then you can call CString's GetBuffer() or even preferably GetString() method which is more better to get LPCTSTR. The advantage is CString class will perform any conversions required automatically for you. No need to worry about Unicode settings.
LPCTSTR pszName = strName.GetString();
Can I somehow use inline assembly in Haskell (similar to what GCC does for C)?
I want to compare my Haskell code to the reference implementation (ASM) and this seems the most straightforward way. I guess I could just call Haskell from C and use GCC inline assembly, but I'm still interested if I can do it the other way around.
(I'm on Linux/x86)
There are two ways:
Call C via the FFI, and use inline assembly on the C side.
Write a CMM fragment that calls C (without the FFI), and uses inlined assembly.
Both solutions use inline assembly on the C side. The former is the most idiomatic. Here's an example, from the rdtsc package:
cycles.h:
static __inline__ ticks getticks(void)
{
unsigned int tbl, tbu0, tbu1;
do {
__asm__ __volatile__ ("mftbu %0" : "=r"(tbu0));
__asm__ __volatile__ ("mftb %0" : "=r"(tbl));
__asm__ __volatile__ ("mftbu %0" : "=r"(tbu1));
} while (tbu0 != tbu1);
return (((unsigned long long)tbu0) << 32) | tbl;
}
rdtsc.c:
unsigned long long rdtsc(void)
{
return getticks();
}
rdtsc.h:
unsigned long long rdtsc(void);
rdtsc.hs:
foreign import ccall unsafe "rdtsc.h" rdtsc :: IO Word64
Finally:
A slightly non-obvious solution is to use the LLVM or Harpy packages to call some generated assembly.