Writing access violation while using qsort() - c++

I am using qsort c++ function. I am passing wordArr in my insert function. The objective is to sort the letters for each word belonging to wordArr.However, while using qsort, I get write access violation. Please let me know, where is my mistake.
char* wordArr[]={"cat","bat","dog"};
int tableClass::compChar(const void* a, const void* b)//in my header file this is static
{
return *(const char*)a - *(const char*)b;
}
void tableClass::insert(char* wordArr[],const int size)
{
for (int i = 0; i < size; i++)
{
qsort(wordArr[i], strlen(wordArr[i]), sizeof(char),tableClass::compChar);
}
}

There are several problems with your code:
1) The parameters are wrong, look at the documentation
2) You're trying to modify read-only memory by reordering an array of pointers to strings allocated into a read-only area. That is not allowed and can result in undefined behavior, i.e. anything could happen.
I would suggest using std::sort for this kind of things and possibly use a stl vector
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
void sort_stuff(std::vector<std::string>& arr)
{
sort(arr.begin(), arr.end());
}
bool myfunction (char *i,char *j) {
int res = strcmp(i,j); // Needed to compare all characters
return (res < 0) ? true : false; // Weak ordering criterion
}
int main() {
std::vector<std::string> arr;
arr.push_back("cat");
arr.push_back("dog");
arr.push_back("bat");
sort_stuff(arr);
// --- edit: if you really want to use a char array ---
char cat[] = "cat";
char bat[] = "bat";
char dog[] = "dog";
char* wordArr[]={cat, bat, dog};
sort(wordArr, wordArr+sizeof(wordArr)/sizeof(char*), myfunction);
cout << wordArr[0] << wordArr[1] << wordArr[2];
return 0;
}
Try it live: http://ideone.com/ErEWnb
Edit: I'm not sure why you really want to use a char array but in case you really need it, you should
1) Put those into writeable memory (e.g. local memory, not string literals)
2) Specify the comparison function since if you pass a char pointers array straight away to sort you would compare the pointers instead of the data they point to. And make sure you compare all characters of the strings. strcmp does what you want
bool myfunction (char *i,char *j) {
int res = strcmp(i,j); // Needed to compare all characters
return (res < 0) ? true : false; // Weak ordering criterion
}
...
char cat[] = "cat";
char bat[] = "bat";
char dog[] = "dog";
char* wordArr[]={cat, bat, dog};
sort(wordArr, wordArr+sizeof(wordArr)/sizeof(char*), myfunction);
cout << wordArr[0] << wordArr[1] << wordArr[2];

Your code attempts to sort the characters of each string.
char* wordArr[] = { "cat", "bat", "dog" };
Is an array of pointers to string literals. No matter that you store the location of those character literals as char* and not as char const* (which is only possible due to the wish of the c++ standards committee to preserve backwards compatibility), changing a string literal causes undefined behavior.
In your case, the storage for the string literals will be allocated in read only memory, leading to an access violation when you attempt to write it.
By storing the string literals in memory under your own control, the access violation does not happen:
char cat[] = "cat";
char bat[] = "bat";
char dog[] = "dog";
char* wordArr[]={cat, bat, dog};

Related

Why casting a quoted string to "string &" causes a crash?

Please note that's just a curious question, I don't need a problem solution!
I have a method that takes in a string reference (string &some_string) and only reads from referenced string. Writing some code I forgot that it needs a reference and passed a quoted string (not a variable, just like "something") and IDE suggested casting it to string reference, as it won't compile. I didn't give it a thought and applied the suggestion (now passing (string &) "something"). And my program crashed as it reached this piece of code. So, why exactly would it cause a crash, compiling without even a warning (g++, c++11)? I don't really understand it since I'm only reading from this string.
Example:
#include <string>
#include <iostream>
using namespace std;
class CharSet
{
private:
const string basis = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const int N = 26;
string array; // string containing all element of the set
int length;
bool add_element(char chr) // Add an element (as char) if not already. Returns true if added, false if not.
{
bool b = false;
if (!in_set(chr) && basis.find(chr) != string::npos) {
array += chr;
length++;
b = true;
}
return b;
}
bool in_set(char chr) const // Checks whether an element (as char) is in set. Returns corresponding bool value.
{
bool b = false;
if (array.find(chr) != string::npos) b = true;
return b;
}
public:
explicit CharSet(string& str) // str - string of possible elements
{
array = "";
length = 0;
int len = (int) str.length();
for (int i = 0; i < len; i++)
add_element(str[i]);
if (str.length() != length)
cout << "\nSome mistakes corrected. Elements read: " << array << endl;
}
};
int main()
{
CharSet A((string &)"AKEPTYUMRX");
getchar();
return 0;
}
A cast like this
(string)"a string literal"
constructs a new std::string by passing "a string literal" as an argument to its constructor. It is equivalent to static_cast<std::string>("a string literal"). It is completely valid, even though C-style casts in C++ are a bad idea in general.
On the other hand, a cast like this
(string&)"a string literal"
constructs a reference to an std::string object that resides at the same location as the string literal. Since there is no such object at that location, using this reference results in undefined behaviour (often expressed as a crash). This cast is equivalent to reinterpret_cast<std::string&>("a string literal"). You might know that reinterpret_cast is dangerous and should be avoided as much as possible. With reinterpret_cast, the compiler trusts the programmer nearly totally, which is not really a wise thing to do, but such is the C++ way.
For your function to be able to accept a string literal, it should have a const std::string& parameter, or perhaps better, if you are using C++17, an std::string_view.

How do I convert a vector<string> to a const char* const* in c++?

I am trying to convert data into the right format for a specific unit test.
The task is to mine a set of words, the unit tests will make sure the results are correct. I have no access to the unit tests, just the declaration which takes a const char* const* Result.
So I need to get my
std::vector<string> Words;
to
const char* const* Result;
divided by a non-alpha char (for example space).
I am aware that this is a constant pointer to a constant character, so I am not sure what to do here since they both constant?
Any pointers (word pun not really intended) are appreciated!
You cannot meaningfully convert one to the other. However, you can convert an array of std::string into an array of pointers to char, and a pointer to the first element of such array would be compatible with your desired result:
std::vector<const char*> Ptrs;
std::transform(
std::cbegin(Words), std::cend(Words),
std::back_inserter(Ptrs),
[](auto& str) { return str.c_str(); }
);
const char* const* Result = Ptrs.data();
Just remember that the strings themselves are still stored in the std::string objects and those pointers within the new vector are only valid as long as the strings in the original vector exist, aren't resized, and the original vector itself isn't resized.
And the pointer to first element of the new vector is only valid as long as that vector exists and isn't resized.
Seems easy enough
#include <algorithm>
#include <functional>
// ...
std::vector<char const*> result_owner(Words.size());
std::transform(begin(Words), end(Words), begin(result_owner),
std::mem_fn(&std::string::c_str));
const char* const* Result = result_owner.data();
Just because Result must provide a const view of the buffer, doesn't mean the buffer has to really be const itself. So it's just another vector that we obtain by projecting Words on the std::string::c_str member.
After that Result can simply be another reference to result_owner.data();.
This of course assumes that Result doesn't have to own the buffer it points at. Owning raw pointers are best avoided.
And the caveman way to do it :)
#include <iostream>
#include <vector>
#include <string>
#include <string.h>
using namespace std;
char **foo(const vector<string> &vec_of_strings)
{
int num_strings = vec_of_strings.size();
int max_str_len = 0;
for (int i=0;i<num_strings;i++)
{
if (max_str_len < vec_of_strings[i].length()) {
max_str_len = vec_of_strings[i].length();
}
}
// for null termination ...
max_str_len++;
char **result = (char **) malloc(num_strings);
for (int i=0;i<num_strings;i++)
{
result[i] = (char *) malloc(max_str_len);
strcpy(result[i],vec_of_strings[i].c_str());
}
return result;
}
int main(int argc, char **argv)
{
vector<string> vec_of_strings;
vec_of_strings.push_back("Long");
vec_of_strings.push_back("Livvvvvvvve");
vec_of_strings.push_back("The");
vec_of_strings.push_back("King");
const char * const * Result = foo(vec_of_strings);
for (int i=0;i<4;i++)
{
printf("%s\n",Result[i]);
}
}

Map C-style string to int using C++ STL?

Mapping of string to int is working fine.
std::map<std::string, int> // working
But I want to map C-style string to int
For example:
char A[10] = "apple";
map<char*,int> mapp;
mapp[A] = 10;
But when I try to access the value mapped to "apple" I am getting a garbage value instead of 10. Why it doesn't behave the same as std::string?
map<char*,int> mapp;
They key type here is not "c string". At least not, if we define c string to be "an array of characters, with null terminator". The key type, which is char*, is a pointer to a character object. The distinction is important. You aren't storing strings in the map. You are storing pointers, and the strings live elsewhere.
Unless you use a custom comparison function object, std::map uses operator<(const key_type&,key_type&) by default. Two pointers are equal if, and only if they point to the same object.
Here is an example of three objects:
char A[] = "apple";
char B[] = "apple";
const char (&C)[6] = "apple"
First two are arrays, the third is an lvalue reference that is bound to a string literal object that is also an array. Being separate objects, their address is of course also different. So, if you were to write:
mapp[A] = 10;
std::cout << mapp[B];
std::cout << mapp[C];
The output would be 0 for each, because you hadn't initialized mapp[B] nor mapp[C], so they will be value initialized by operator[]. The key values are different, even though each array contains the same characters.
Solution: Don't use operator< to compare pointers to c strings. Use std::strcmp instead. With std::map, this means using a custom comparison object. However, you aren't done with caveats yet. You must still make sure that the strings must stay in memory as long as they are pointed to by the keys in the map. For example, this would be a mistake:
char A[] = "apple";
mapp[A] = 10;
return mapp; // oops, we returned mapp outside of the scope
// but it contains a pointer to the string that
// is no longer valid outside of this scope
Solution: Take care of scope, or just use std::string.
It can be done but you need a smarter version of string:
struct CString {
CString(const char *str) {
strcpy(string, str);
}
CString(const CString &copy); // Copy constructor will be needed.
char string[50]; // Or char * if you want to go that way, but you will need
// to be careful about memory so you can already see hardships ahead.
bool operator<(const CString &rhs) {
return strcmp(string, rhs.string) < 0;
}
}
map<CString,int> mapp;
mapp["someString"] = 5;
But as you can likely see, this is a huge hassle. There are probably some things that i have missed or overlooked as well.
You could also use a comparison function:
struct cmpStr{
bool operator()(const char *a, const char *b) const {
return strcmp(a, b) < 0;
}
};
map<char *,int> mapp;
char A[5] = "A";
mapp[A] = 5;
But there is a lot of external memory management, what happens if As memory goes but the map remains, UB. This is still a nightmare.
Just use a std::string.

How to convert a vector<wstring> to a wchar_t**?

I need to create a C compatible (friendly) return type so that my C++ functions can be used to work with C-based functions.
How I can convert a vector of wstring to a wchar_t** array?
You can iterate through the wstring vector and add each wstring::c_str() to your wchart_t** array.
Far better to avoid doing this at all if you possibly can.
If you really have no choice, you'd basically do something like allocating an array of pointers, then allocating space for each string, and copying each individual string in the input to the buffer you allocated.
wchar_t *dupe_string(std::wstring const &input) {
wchar_t *ret = new wchar_t[input.size()+1];
wcscpy(ret, input.c_str());
return ret;
}
wchar_t **ruin(std::vector<std::wstring> const &input) {
wchar_t **trash = new wchar_t*[input.size()];
for (int i=0; i<input.size(); i++)
trash[i] = dupe_string(input[i]);
return trash;
}
Based on the comments, however, I have some misgivings about this applying to the current situation though -- this assumes the input is wide strings, which would typically mean UTF-16 or UTF-32/UCS-4. If the input is really in the form of UTF-8, then the storage elements you're dealing with will really be char, not wchar_t, so your input should be narrow strings (std::string) and the matching output char ** rather than wchar_t **.
wstring is a templated instantiation of basic_string, so its c_str() function returns wchar_t*.
So, you can do something like
std::vector<const wchar_t*> pointers;
pointers.reserve(wstrVec.size());
for (auto it = wstrVec.begin(); it != wstrVec.end(); ++it) {
pointers.push_back(it->c_str());
}
const whcar_t** cptr = pointers.data();
Without more context it's difficult to advise the best way to deal with scope/lifetime issues. Are you writing a library (which suggests you have no control over scope) or providing an api for callbacks from C code you are supervising?
A common approach is to provide a sizing api so that the caller can provide a destination buffer of appropriate size:
size_t howManyWstrings()
{
return wstrVec.size();
}
bool getWstrings(const wchar_t** into, size_t intoSize /*in pointers*/)
{
const size_t vecSize = wstrVec.size();
if (intoSize < vecSize || into == nullptr)
return false;
for (size_t i = 0; i < vecSize; ++i) {
into[i] = wstrVec[i].c_str();
}
return true;
}
It sounds like your C function is expecting a pointer to a wchar_t buffer, and to be able to move this pointer around.
Well, this is mostly easy, though you'll have to manage the lifetime of the pointer. To that end, I suggest not doing this as a return type (and thus letting C ruin your API, not to mention your code's sanity), but performing this logic at the call site of the C function:
/** A function that produces your vector */
std::vector<wchar_t> foo();
/** The C function in question */
void theCFunction(wchar_t**);
int main()
{
std::vector<wchar_t> v = foo();
wchar_t* ptr = &v[0];
theCFunction(&ptr);
}
BTW from the question and some comments it sounds like you misunderstand what char and wchar_t are — they sit below the encoding layer and if you have UTF-8 then you should be storing each byte of your UTF-8 string as, well, as a single byte. This means using chars, as in a std::string. Sure, each individual byte in that string will not necessarily represent a single logical unicode character, but then that is not the point of it.
This is the function for converting a vector of std::wstring to a wchar_t** based string. It also won't leak any memory because of using that DisposeBuffer(); call unlike other answers.
wchar_t ** xGramManipulator::GetCConvertedString(vector< wstring> const &input)
{
DisposeBuffer(); //This is to avoid memory leak for calling this function multiple times
cStringArraybuffer = new wchar_t*[input.size()]; //cStringArraybuffer is a member variable of type wchar_t**
for (int i = 0; i < input.size(); i++)
{
cStringArraybuffer[i] = new wchar_t[input[i].size()+1];
wcscpy_s(cStringArraybuffer[i], input[i].size() + 1, input[i].c_str());
cStringArraySize++;
}
return cStringArraybuffer;
}
And this is the DisposeBuffer Helper Function to avoid memory leaks:
void xGramManipulator::DisposeBuffer(void)
{
for (size_t i = 0; i < cStringArraySize; i++)
{
delete [] cStringArraybuffer[i];
}
delete [] cStringArraybuffer;
cStringArraybuffer = nullptr;
cStringArraySize = 0;
}
And prior to these allocate a dummy space in your constructor:
xGramManipulator::xGramManipulator()
{
//allocating dummy array so that when we try to de-allocate it in GetCConvertedString(), dont encounter any undefined behavior
cStringArraybuffer = new wchar_t*[1];
cStringArraySize = 0;
for (int i = 0; i < 1; i++)
{
cStringArraybuffer[i] = new wchar_t[1 + 1];
cStringArraySize++;
}
}
And it's all done.

C++ error - returning a char array

Consider the following code:
char CeaserCrypt(char str[256],int key)
{
char encrypted[256],encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); i++)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
Visual Studio 2010 gives an error because the function returns an array. What should I do?
My friend told me to change the signature to void CeaserCrypt(char str[256], char encrypted[256], int key). But I don't think that is correct. How can I get rid of the compile error?
The return type should be char * but this'll only add another problem.
encrypted is "allocated" on the stack of CeaserCrypt and might not be valid when the function returns. Since encrypted would have the same length as the input, do:
int len = strlen(str);
char *encrypted = (char *) malloc(len+1);
encrypted[len] = '\0';
for (int i = 0; i < len; i++) {
// ...
}
Don't forget to deallocate the buffer later, though (with free()).
EDIT: #Yosy: don't feel obliged to just copy/paste. Use this as a pointer to improve your coding practice. Also, to satisfy criticizers: pass an already allocated pointer to your encryption routine using the above example.
It wants you to return a char* rather than a char. Regardless, you shouldn't be returning a reference or a pointer to something you've created on the stack. Things allocated on the stack have a lifetime that corresponds with their scope. After the scope ends, those stack variables are allowed to go away.
Return a std::vector instead of an array.
std::vector<char> CeaserCrypt(char str[256],int key)
{
std::vector<char> encrypted(256);
char encryptedChar;
int currentAsci;
encrypted[0] = '\0';
for(int i = 0; i < strlen(str); ++i)
{
currentAsci = (int)str[i];
encryptedChar = (char)(currentAsci+key);
encrypted[i] = encryptedChar;
}
return encrypted;
}
There's another subtle problem there though: you're casting an integer to a character value. The max size of an int is much larger than a char, so your cast may truncate the value.
Since you're using C++ you could just use an std::string instead. But otherwise, what your friend suggested is probably best.
There are a few problems here. First up:
char CeaserCrypt(char str[256],int key)
As others have pointed out, your return type is incorrect. You cannot return in a single character an entire array. You could return char* but this returns a pointer to an array which will be allocated locally on the stack, and so be invalid once the stack frame is removed (after the function, basically). In English, you'll be accessing that memory address but who knows what's going to be there...
As your friend suggested, a better signature would be:
void CeaserCrypt(char* encrypted, const char str*, const size_t length ,int key)
I've added a few things - a size_t length so you can process any length string. This way, the size of str can be defined as needed. Just make sure char* encrypted is of the same size.
Then you can do:
for(int i = 0; i < length; i++)
{
// ...
For this to work your caller is going to need to have allocated appropriately-sized buffers of the same length, whose length you must pass in in the length parameter. Look up malloc for C. If C++, use a std::string.
If you need C compatibility make encrypted string function argument.
If not, than use C++ std::string instead C style string.
And also In your code encrypted string isn't ending with '\0'
The problem with the original code is that you are trying to return a char* pointer (to which your local array decayed) from a function that is prototyped as one returning a char. A function cannot return arrays in C, nor in C++.
Your friend probably suggested that you change the function in such a way, that the caller is responsible for allocation the required buffer.
Do note, that the following prototypes are completely equal. You can't pass an array as a parameter to normal function.
int func(char array[256]);
int func(char* array);
OTOH, you should (if you can!) decide the language which you use. Better version of the original (in C++).
std::vector<unsigned char> CeaserCrypt(const std::string& str, const int key)
{
std::vector<unsigned char> encrypted(str.begin(), str.end());
for (std::vector<unsigned char>::iterator iter = vec.begin();
iter != vec.end(); ++iter) {
*iter += key;
}
return vec;
}
Do note that overflowing a signed integer causes undefined behavior.
VS2010 is "yelling" at you because you are trying to return a value that is allocated on the stack, and is no longer valid once your function call returns.
You have two choices: 1) Allocate memory on the heap inside your function, or 2) use memory provided to you by the caller. Number 2 is what your friend in suggesting and is a very good way to do things.
For 1, you need to call malloc() or new depending on whether you are working in C or C++. In C, I'd have the following:
char* encrypted = malloc(256 * sizeof(char));
For C++, if you don't want to use a string, try
char* encrypted = new char[256];
Edit: facepalm Sorry about the C noise, I should have looked at the question more closely and realized you are working in C++.
You can just do your Ceaser cipher in place, no need to pass arrays in and out.
char * CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
return str;
}
As a further simplification, skip the return value.
void CeaserCrypt(char str[256], int key)
{
for(unsigned i = 0; i < strlen(str); i++)
{
str[i] += key;
}
}
well what you're returning isn't a char, but a char array. Try changing the return type to char*(char* and a char array are ostensibly the same thing for the compiler)
char* CeaserCrypt(char str[256],int key)
EDIT: as said in other posts, the encrypted array will probably not be valid after the function call. you could always do a new[] declaration for encrypted, remembering to delete[] it later on.