i am working on a piece of code right now and got a problem with void pointer and char. basically, within the serialize function, we would have a new char. we would need to store that char in buffer. and here is the signature of serialize function.
void serialize(void *buffer,
//some other inputs here
){
std::string str = "";
/*some code here, store the final output in str first*/
char* charStr = new char[str.size()];
strcpy(charStr,str.c_str());
buffer = static_cast<void*>(charStr);
}
using the function like this,
char buffer[256];
serialize(buffer,
//some other inputs here
);
However, the data stored in buffer would be something real strange. I changed the void pointer in the signature to char pointer as a temporary solution. However, i know there must be a better one.
If you want to fill a buffer, you cannot assign to it (that will just overwrite the pointer, leaving the original buffer contents intact). You also do not need a temporary buffer in serialize (charStr). You can directly strcpy to the output buffer, like this:
void serialize(void *buffer
){
std::string str = "foo bar baz";
strcpy((char *)buffer, str.c_str());
}
define it as
void serialize(void *& buffer,
//some other inputs here
){
use pointer as parameter, remember to delete the buffer
char* buffer;
serialize(buffer,
//some other inputs here
);
Related
I'm having a weird and unexpected result in my code and I'd like your support to explain me what happens here.
I have a structure of a confiration :
struct sConfig {
const char* ssid;
const char* password;
}
I'm loading this configuration using LittleFS from a deserialized json :
config.ssid = json["ssid"]; // so this is coming from the FS in a json file
config.password = json["password"]; // so this is coming from the FS in a json file
So far, all is fine, I can print out the value using
Serial.println(config.ssid);
I'm then calling an internal void function
startWiFi(config.ssid, config.password);
void startWiFi(const char* ssid, const char* psswd) {
Serial.println(ssid);
Serial.println(psswd);
}
As a result, the console returns :
⸮
and
?:⸮?#⸮8⸮?<9⸮?⸮8⸮?:⸮?#⸮8⸮?<9⸮?⸮8⸮?:⸮?#⸮8⸮?<9⸮?⸮8⸮?.:⸮?#⸮
What can be wrong in my variables ?
Please help me as I'm stuck.
Thanks a lot.
To fix the issue I'd avoid copying a pointer and copy the actual data.
So, instead of config.password = json["password"];
I'd declare ssid and password as char arrays and copy the values from the json with strncpy()
struct sConfig {
char ssid[32];
char password[64];
}
or I'd allocate them on the spot with a custom copy function
char * myCopy (char *destination, const char *source)
{
// I'm using 64 because is the max length of WPA2-PSK passwords
size_t len = strnlen(destination, 64);
destination = malloc((num + 1) * sizeof(char));
strncpy(destination, source, num);
return destination;
}
....
myCopy(config.ssid, json["ssid"]);
myCopy(config.password, json["password"]);
What's probably happening here is a use-after-free bug.
At config.ssid = json["ssid"] you copy a pointer to the internal memory of the json object. It's probably valid at the time of that copy (so the print succeeds), but when the json changes its state or gets deallocated, you get garbage at that memory address.
The solution is - as suggested in the other answer - copy the whole string and not just its address.
I have a method which returns the constant char pointer. It makes use of a std::string and finally returns its c_str() char pointer.
const char * returnCharPtr()
{
std::string someString;
// Some processing!
return someString.c_str();
}
I have got a report from Coverity tool that the above is not a good usage. I have googled and have found that the char pointer returned would be invalidated as soon as someString meets its destruction.
Given this, how does one fix this issue? How can I return a char pointer accurately?
Returning std::string would resolve this issue. But I want to know if there is any other means of doing this.
What happens in this code is:
const char * returnCharPtr()
{
std::string someString("something");
return someString.c_str();
}
instance of std::string is created - it is an object with automatic storage duration
pointer to the internal memory of this string is returned
object someString is destructed and the its internal memory is cleaned up
caller of this function receives dangling pointer (invalid pointer) which yields undefined behavior
The best solution is to return an object:
std::string returnString()
{
std::string someString("something");
return someString;
}
When calling your function, DO NOT do this:
const char *returnedString = returnString().c_str();
because returnedString will still be dangling after the returned std::string is destructed. Instead store the entire std::string:
std::string returnedString = returnString();
// ... use returnedString.c_str() later ...
In C++, the simplest thing to do is to just return a std::string (which is also efficient thanks to optimizations like RVO and C++11 move semantics):
std::string returnSomeString()
{
std::string someString;
// some processing...
return someString;
}
If you really need a raw C char* pointer, you can always call .c_str() on the returned value, e.g.
// void SomeLegacyFunction(const char * psz)
// .c_str() called on the returned string, to get the 'const char*'
SomeLegacyFunction( returnSomeString().c_str() );
If you really want to return a char* pointer from the function, you can dynamically allocate string memory on the heap (e.g. using new[]), and return a pointer to that:
// NOTE: The caller owns the returned pointer,
// and must free the string using delete[] !!!
const char* returnSomeString()
{
std::string someString;
// some processing...
// Dynamically allocate memory for the returned string
char* ptr = new char[someString.size() + 1]; // +1 for terminating NUL
// Copy source string in dynamically allocated string buffer
strcpy(ptr, someString.c_str());
// Return the pointer to the dynamically allocated buffer
return ptr;
}
An alternative is to provide a destination buffer pointer and the buffer size (to avoid buffer overruns!) as function parameters:
void returnSomeString(char* destination, size_t destinationSize)
{
std::string someString;
// some processing...
// Copy string to destination buffer.
// Use some safe string copy function to avoid buffer overruns.
strcpy_s(destination, destinationSize, someString.c_str());
}
As this question is flagged C, do this:
#define _POSIX_C_SOURCE 200809L
#include <string.h>
const char * returnCharPtr()
{
std::string someString;
// some processing!.
return strdup(someString.c_str()); /* Dynamically create a copy on the heap. */
}
Do not forget to free() what the function returned if of no use anymore.
Well, COVERITY is correct. The reason your current approach will fail is because the instance of std::string you created inside the function will only be valid for as long as that function is running. Once your program leaves the function's scope, std::string's destructor will be called and that will be the end of your string.
But if what you want is a C-string, how about...
const char * returnCharPtr()
{
std::string someString;
// some processing!.
char * new_string = new char[someString.length() + 1];
std::strcpy(new:string, someString.c_str());
return new_string;
}
But wait... that's almost exactly as returning a std::string, isn't it?
std::string returnCharPtr()
{
std::string someString;
// some processing!.
return new_string;
}
This will copy your string to a new one outside of the function's scope. It works, but it does create a new copy of the string.
Thanks to Return Value Optimization, this won't create a copy (thanks for all corrections!).
So, another option is to pass the parameter as an argument, so you process your string in a function but don't create a new copy. :
void returnCharPtr(std::string & someString)
{
// some processing!.
}
Or, again, if you want C-Strings, you need to watch out for the length of your string:
void returnCharPtr(char*& someString, int n) // a reference to pointer, params by ref
{
// some processing!.
}
The best way would be to return an std::string, which does automatic memory management for you. If, on the other hand, you were really into returning a const char* which points to some memory allocated by you from within returnCharPtr, then it'd have to be freed by someone else explicitly.
Stay with std::string.
A solution which hasn't been evoked in the other answers.
In case your method is a member of a class, like so:
class A {
public:
const char *method();
};
And if the class instance will live beyond the usefulness of the pointer, you can do:
class A {
public:
const char *method() {
string ret = "abc";
cache.push_back(std::move(ret));
return cache.last().c_str();
}
private:
vector<string> cache; //std::deque would be more appropriate but is less known
}
That way the pointers will be valid up till A's destruction.
If the function isn't part of a class, it still can use a class to store the data (like a static variable of the function or an external class instance that can be globally referenced, or even a static member of a class). Mechanisms can be done to delete data after some time, in order to not keep it forever.
Your options are:
Return std::string
Pass a buffer to returnCharPtr() that will hold the new character buffer. This requires you to verify the provided buffer is large enough to hold the string.
Create a new char array inside returnCharPtr(), copy the buffer into the new one and return a pointer to that. This requires the caller to explicitly call delete [] on something they didn't explicitly create with new, or immediately place it into a smart pointer class.
This solution would be improved if you returned a smart pointer, but it really just makes more sense to return a std::string directly.
Choose the first one; return std::string.
It is by far the simplist and safest option.
The problem is that someString is destroyed at the end of the function, and the function returns the pointer to non-existing data.
Don't return .c_str() of string that could be destroyed before you use the returned char pointer.
Instead of...
const char* function()
{
std::string someString;
// some processing!
return someString.c_str();
}
//...
useCharPtr(function());
use
std::string function()
{
std::string someString;
// some processing!
return someString;
}
//...
useCharPtr(function().c_str());
If you have the freedom to change the return value of returnCharPtr, change it to std::string. That will be the cleanest method to return a string. If you can't, you need to allocate memory for the returned string, copy to it from std::string and return a pointer to the allocated memory. You also have to make sure that you delete the memory in the calling function. Since the caller will be responsible for deallocating memory, I would change the return value to char*.
char* returnCharPtr()
{
std::string someString;
// some processing!.
char* cp = new char[someString.length()+1];
strcpy(cp, someString.c_str());
return cp;
}
You can pass in a pointer to your string, and have the method manipulate it directly (i.e., avoiding returns altogether)
void returnCharPtr(char* someString)
{
// some processing!
if(someString[0] == 'A')
someString++;
}
I was facing this problem when implementing https://en.cppreference.com/w/cpp/error/exception/what what() virtual function of std::exception offspring.
Well the signature must be
virtual const char* what() const throw();
This means however that returning std::string is not an option unless you want to rewrite standard library. I would like to know what these people saying "always return std::string" would think about standard library developers...
To allocate dynamic array is not a good idea in exception handling. I end up with the following solution. The whole class will be just wrapper for the final message that could not be modified even inside constructor.
class KCTException : public exception
{
const char* file;
const int line;
const char* function;
const std::string msg;
const std::string returnedMessage;
public:
KCTException(std::string& msg, const char* file, int line, const char* function)
: file(file)
, line(line)
, function(function)
, msg(msg)
, returnedMessage(io::xprintf("KCTException in [%s#%s:%d]: %s", function, file, line, msg.c_str()))
{
}
const char* get_file() const { return file; }
int get_line() const { return line; }
const char* get_function() const { return function; }
const std::string& get_msg() const { return msg; }
const char* what() const throw()
{
return returnedMessage.c_str();
}
};
Here io::xprintf is my wrapper function that behaves as printf but returns string. I found no such function in a standard library.
I have been given this definitions, the function should return what is in info->phrase. However info->phrase can contain a string in which case I can only make it return the first char on info->phrase. Is there a way to make a string compatible with the char type? I am new to c++.
struct rep_info {
int num;
char *phrase;
};
I´ve tried few thing but get type errors, this was my latest attempt
char *phrase_info(rep_info info) {
char text[std::strlen(info->phrase) + 1];
text = info->phrase;
return text;
}
Since you said you have been given these definitions, let's fix the problem with the current setup first. Looking at your function, you are trying to copy into this local array (incorrectly I might add), and return this local variable. There are a number of things wrong with this, including the syntax and the fact that the local variable is destroyed when the function exits.
If you just need to get the value of the phrase member variable, the simplest solution would be to just access the member variable directly and return it:
char *phrase_info(rep_info info) {
return info.phrase; //since info is not a pointer, use the '.' accessor
}
If you mean to pass a pointer to the function, you would re-write it like this:
char *phrase_info(rep_info *info) {
return info->phrase;
}
But it seems like you feel the need to copy the contents of info->phrase into a new memory space? If so, then you would do something like this where you first allocate new memory and return this buffer:
char *phrase_info(rep_info *info) {
char *buf = new char[std::strlen(info->phrase) + 1];
std::strcpy(buf,info->phrase); //copies info->phrase into buf
return buf;
}
You would then need to use delete on the returned memory value to clean up the memory allocated by new, otherwise you will have a memory leak.
Overall, all the above solution would potentially solve the problem given some parameters you haven't made clear. To round this out, this should be written more like:
class rep_info {
private:
int num;
std::string phrase;
public:
rep_info(int n, std::string p) : num(n), phrase(p) {}
std::string get_phrase() { return phrase; }
// other functions
};
//later in the code
rep_info info(...);
info.get_phrase();
Ideally, you would wrap these member variables into their own object with corresponding member functions that can get and set these values. Moreover, for handling strings in C++, std::string is the preferred option for storing, copying, modifying, etc. strings over the older char * C-style string.
I'm trying to read the content of a file from an enclave using OCalls.
enclave.edl:
untrusted {
void ocall_print_string([in, string] const char *str);
void ocall_read_IMA_file([in, string] const char *filename, [out] char *buf, [out] int *size);
};
enclave.cpp:
void printf(const char *fmt, ...) {
ocall_print_string(fmt);
}
void read_IMA_file(const char *filename, char *buf, int *size) {
ocall_read_IMA_file(filename, buf, size);
printf(buf);
}
//whereas the read_IMA_file function is called with
char *buf;
int size;
read_IMA_file("test.txt", buf, &size);
implementation of ocall functions in the application:
void ocall_print_string(const char *str) {
printf("%s\n", str);
}
void ocall_read_IMA_file(const char *filename, char *content, int *size) {
content = (char*) malloc(sizeof(char) * 10);
memset(content, '\0', sizeof(char) *10);
char tmp[] = "1234567890";
copy(&tmp[0], &tmp[9], content);
cout << content << endl;
}
But the result I receive is the following:
123456789 (null)
I'm not sure what I'm doing wrong?
In the above program, the "read_IMA_file" trusted function is called with pointer variable(OUT pointer) of type character.Here we are passing the pointer variable without any memory allocation.
"read_IMA_file" initiate a OCall that allocate memory and do "Copy" operation.Now the allocated memory is valid within the untrusted region. So we are getting expected result for the "cout<
Since there is no trusted memory allocated for "content"(before calling Ocall), no copy back operation happens in "OUT" pointer during Ocall returns.
So "buf" doesn't contain any valid data while doing "print(buf)" after Ocall returns in trusted region.
Please try with valid OUT pointer to character buffer(with some memory allocation) or IN and OUT pointer to String buffer.
If you expect it to output 1234567890, then you may need to malloc(11) instead of malloc(10), plus the way you are using copy may contain a bug too.
copy(&tmp[0], &tmp[9], content);
is copying 123456789 to the content, it exclude the the last iterator &tmp[9] as I understand. For more detail, you may want to look at: http://www.cplusplus.com/reference/algorithm/copy/
Also, I think you are not reading in any content from file "test.txt" either.
I need to read a stream out of a binary file from a function. I'd like to call it by reference of that char * to have a pointer to the start of the stream in the end. However, Every attempt of mine, did either not change the pointer, or caused an Memory Access Violation.
I call the method from another function.
Here the calling function:
APP_ERROR EncryptionHandler::encryptFile(char *file)
{
char *i_Stream = ""; // I get a compiler error if I dont initialize this
if(this->readFileStream("picture.png", i_Stream) != OPERATION_SUCCESSFUL) // Call the function and return a custom error, if the function does so
return ERROR_FILE_READING;
}
Here the function to read the file
APP_ERROR EncryptionHandler::readFileStream(char *fileName, char *Stream)
{
char *fileStream;
FILE *file = fopen(fileName, "rb");
// Some logic to get the file size
fileStream = new char[maxFileSize];
fread(fileStream, 1, maxFileSize, file); // Fill the stream with the fread function
fclose(file);
Stream = fileStream; // Set the given Pointer to my fileStream pointer
return OPERATION_SUCCESSFUL;
}
How ever in the calling function, the Variable i_Stream has never changed. It's still pointing to "" which causes problems in my program, later
I don't get this, as I set the given pointer = my fileStream pointer
However following methods didn't work aswell:
this->readFileStream("picture.png", char &i_Stream);
i_Error EncryptionHandler::readFileStream(char *fileName, char **Stream)
this->readFileStream("picture.png", char *i_Stream);
i_Error EncryptionHandler::readFileStream(char *fileName, char &Stream)
Procedures like memcpy aren't the right thing I think, as I've already got this pointer to my Stream. And they caused Access Violation Errors aswell...
There must be an easy way to give that stream pointer from within my file reading function to my calling methods variable...
I cannot use the return value of the function, because I am using my own Error system, as you can see...
It is also binary Data and the use of any strings is not welcome.
So what is the proper way of calling a char array by reference?
You should declare EncryptionHandler::readFileStream() as
APP_ERROR EncryptionHandler::readFileStream(char *fileName, char *&Stream)
Note the type of parameter Stream. With reference of pointer, you can pass the change of Stream inside readFileStream() back to caller.
Without the reference, the pointer is simply copied into readFileStream().
In addition to what #timrau said, I see a memory allocation problem. I don't see any code that allocates memory to hold the data that you are reading from the file. Something like the code below should work.
PP_ERROR EncryptionHandler::readFileStream(char *fileName, char*& Stream)
{
char *fileStream;
FILE *file = fopen(fileName, "rb");
// Some logic to get the file size
// Allocate memory for the data.
fileStream = new char[maxFileSize];
fread(fileStream, 1, maxFileSize, file); // Fill the stream with the fread function
fclose(file);
Stream = fileStream; // Set the given Pointer to my fileStream pointer
return OPERATION_SUCCESSFUL;
}
You can simplify the function a little bit by just using Stream.
PP_ERROR EncryptionHandler::readFileStream(char *fileName, char*& Stream)
{
FILE *file = fopen(fileName, "rb");
// Some logic to get the file size
// Allocate memory for the data.
Stream = new char[maxFileSize];
fread(Stream, 1, maxFileSize, file); // Fill the stream with the fread function
fclose(file);
return OPERATION_SUCCESSFUL;
}