I'm trying to create a 2D array of c-strings (for a specific school exercise; I'm forced to use c-strings for practice) using dynamic memory allocation. However, it seems that when accessing and writing to the second index of the array (second sub-array), the actual memory location that's used is the same of the first index.
The code:
#include <iostream>
#include <string>
int main()
{
int n_names; std::string current; const int SPACE_FOR_EACH_NAME = 100;
std::cout << "How many names to input? "; std::cin >> n_names; std::cin.ignore();
//dynamically allocate a multi-dimensional array
char** names;
names = new char* [n_names];
for (int i = 0; i < n_names; i++)
names[i] = new char[SPACE_FOR_EACH_NAME];
int count = 0;
while (count < n_names) {
std::cout << "Name " << ++count << ": ";
std::getline(std::cin, current);
names[count-1] = (char*) current.c_str(); //THE TROUBLE SEEMS TO BE HERE
}
for (int i = 0; i < n_names; ++i) {
for (int j = 0; j < SPACE_FOR_EACH_NAME; ++j) {
if (names[i][j] == '\0') break; //termination of the current name
std::cout << names[i][j];
}
std::cout << "\n";
}
//free allocated memory
for (int i = 0; i < n_names; ++i)
delete[] names[i];
delete[] names;
}
What the debugger shows when modifying the 'names' array (consider user inputs 2 names):
+ names[count-1] 0x00affbe8 "dude" char * //here count is 1
+ names[count-1] 0x00affbe8 "noice" char * //here count is 2
And the console just prints "noice" twice.
What's wrong?
The result of current.c_str() should never be stored for any length of time. Doing so is undefined behaviour, but it is likely, as here that that memory pointed to will be reused.
You put the char* from current.c_str() into names[0], then you put a new value into current and put current.c_str() into names[1]. But because you have changed current you also change names[0].
Also, in both cases, you are discarding the pointer you already created with names[i] = new char[SPACE_FOR_EACH_NAME];
This allocates a block of memory and puts it's address into names[0] (0 as a specific example). The next thing that happens with names[0] is names[0] = (char*) current.c_str(); which puts a different address into the variable. The address returned from the new is lost completely, causing a memory leak.
Instead of
names[count-1] = (char*) current.c_str();
try
std::strcpy(names[count-1],current.c_str())
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
the function is to preserve argument array and produce anidentical array in the heap memory that has the even elements to (left) & odd(right), but when i output i find a row of zeros and bunch of random big numbers which look like addresses but I don't think they are, Please help.
int* even_left_odd_right(int arr[], int size1)
{
int* array;
array = new int[size1];
for(int i = 0; i < size1; i++)
array[i] = arr[i];
for(int i = 0, j =0; i < size1; i++)
{
if(array[i] % 2 == 0)
{
int temp = array[j];
array[j] = array[i];
array[i] = temp;
j++;
}
}
return array;
}
int main()
{
int size1;
cout << "Enter size of array:";
cin >> size1;
int* array1;
array1 = new int[size1];
int arr[size1];
cout << "Enter the entries in this array: ";
for(int i = 0; i < size1; i++)
cin >> arr[i];
even_left_odd_right(arr, size1);
for(int i = 0; i < size1; i++)
cout << array1[i] << " ";
delete[] array1;
return 0;
}`
The root cause of all your problems is that you do not use the return value of your function. Besides that, there are more things that should be corrected.
Additionally, we need to mention that what you are obviously learning now, dynamic memory management using new and delete and raw pointers for owned memory, is strongly discourage.
Basically: new, delete and raw pointers for owned memory should NEVER be used in C++.
It is that error prone that is has no place any more in standard C++. You even have an error with leaked memory and do not notice it. The array, that you are dynamically allocating in your function with new, is never deleted.
I know that teachers still do teach this crap, but just for explaining dynamic memory mangement from scratch. So, let's go ahead and use it for now.
You have however some additional errors.
Your function returns the partitioned data. But you never use the functions return value
You are using (for whatever reason??) a so called VLA (Variable Length Array) in int arr[size1];. This is illegal in C++. Real C++ compilers will not allow that.
You are mixing up arr and array1. In the beginning, you are creating array1. After creation, it is not initialized and will contain random values.
Then you call your function with arr and output array1 at the end. So, you will output random data. That is, what you see. Random data.
You could use the build in std::swap function. But I guess that it is prohibited by the teacher. What a shame.
You unneccessarily change the order of the entries in the array with swapping. But this does not harm
Your function simply returns a raw pointer. The outer world does not know anything about that. That is dangerous
You even do not know that arr in your function signature (int arr[]) will decay to a pointer
To quickly fix your code, we could write:
#include <iostream>
int* even_left_odd_right(int arr[], int size1)
{
int* array;
array = new int[size1];
for (int i = 0; i < size1; i++)
array[i] = arr[i];
for (int i = 0, j = 0; i < size1; i++)
{
if (array[i] % 2 == 0)
{
int temp = array[j];
array[j] = array[i];
array[i] = temp;
j++;
}
}
return array;
}
int main()
{
int size1;
std::cout << "Enter size of array:";
std::cin >> size1;
int* array1;
array1 = new int[size1];
//int arr[size1]; NOT ALLOWED in C++
std::cout << "Enter the entries in this array: ";
for (int i = 0; i < size1; i++)
std::cin >> array1[i];
int* array2 = even_left_odd_right(array1, size1);
for (int i = 0; i < size1; i++)
std::cout << array2[i] << " ";
delete [] array1;
delete [] array2;
return 0;
}
But such code should never be used in C++.
Again, I guess I understand requirements from teacher.
By the way. In C++17 you would probaly write the follwoing code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
// Tell user, what to do: Get the number of data to operate on
std::cout << "\nEnter the number of data to operate on: ";
// Read the number of data from the user via std::cin. Check, if number is OK
if (size_t numberOfData{}; (std::cin >> numberOfData) and (numberOfData > 0)) {
// Define the vector for our original data with the size given by the user
std::vector<int> dataOriginal(numberOfData);
// And get the number of specified data from the user
std::cout << "\n\nAnd now, please enter the data\n";
std::copy_n(std::istream_iterator<int>(std::cin), numberOfData, dataOriginal.begin());
// We want to preserve the original input, so, make a copy of that vector
std::vector result(dataOriginal);
// Now partition the output as requested
std::stable_partition(result.begin(), result.end(), [](const int i) { return (i % 2) == 0; });
// Show result to user
std::copy(result.begin(), result.end(), std::ostream_iterator<int>(std::cout, " "));
}
else {
std::cerr << "\nError: Wrong input given for number of data\n\n";
}
}
Please note:
No loops
Input validation
CTAD
No function needed, everthing can be done with one statemennt
I need some help since I'm new to c++, I have a homework question where we should read a name to a char[] and then place that input inside a dynamic array, sort the dynamic array, and then terminate the allocated memory. We have to work with a half-done written program and I don't think I'm getting the input incorrectly in the dynamic array and I have a problem with deallocating memory could someone help with some tips maybe? My contribution to the code is highlighted in ** ** thanks!
const int BUFLEN = 100; // Max length of reading buffer
void sort(char* friendList[], int n); // n is the number of elements
void print(char* friendList[], int n); // n is the number of elements
void terminate(char* friendList[], int n); // n is the number of elements
const int AMOUNT = 5;
int main()
{
char* friends[AMOUNT]; // Dynamic array with AMOUNT pcs of string pointers
char buff[BUFLEN] = { "" }; // Creates a string buffer (null terminated)
int count = 0;
while (count < AMOUNT) // enter AMOUNT number of friends
{
cout << "Name a friend: ";
cin.getline(buff, BUFLEN); // Temporary reading into string buffer
friends[count] = **new char[AMOUNT];** //. . . WRITE CODE allocating memory to the string
// WRITE CODE that adds loaded name to current location in the dynamic array
**strcpy(friends[count], buff);**
++count;
}
sort(friends, count); // Sorts the ‘count’ strings
print(friends, count); // Prints the ‘count’ first names
terminate(friends, count);// Releases all allocated memory space
return 0;
}
void sort(char* friendList[], int n)
{
// WRITE FUNCTION that sorts the strings in the friendList in alphabetical order!
**int result;
for (int i = 0; i < n - 1; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
result = strcmp(friendList[j+1], friendList[j]);
if (result < 0)
swap(friendList[j+1], friendList[j]);
}
}**
}
void print(char* friendList[], int n)
{
// WRITE FUNCTION that prints ‘n’ names from the friendList on screen!
**for (int i = 0; i < n; i++)
{
cout << friendList[i] << " " << i << endl;
}**
}
void terminate(char* friendList[], int n)
{
// WRITE FUNCTION that releases all dynamically allocated memory!
**for (int i = 0; i < n; i++)
{
delete friendList[i];
}
delete [] friendList;
cout << "deleted! ";**
}
I see a few problems with this code:
In main():
not validating that cin.getline() is successful before using the contents of buff.
AMOUNT is the wrong size to use when allocating a new char[] to store in friends[]. The correct size should be either strlen(buff)+1 or cin.gcount().
In terminate() (not to be confused with std::terminate()):
delete[]'ing the input array itself, which was not allocated with new[] to begin with and thus must not be delete[]'ed.
Instead of this statement
friends[count] = new char[AMOUNT];
you need to write
friends[count] = new char[strlen( buff ) + 1];
Pay attention to that the array friends itself is not allocated dynamically. But each its element points to a dynamically allocated array. So the function terminate can look like
void terminate(char* friendList[], int n)
{
// WRITE FUNCTION that releases all dynamically allocated memory!
for (int i = 0; i < n; i++)
{
delete [] friendList[i];
friendList[i] = nullptr;
}
cout << "deleted! ";
}
For this assignment, I need to make a sorted copy of an array the user has given values to. All of my code works as intended, except for this specific part. I need this function (sortedCopy) to print out the sorted version of their array, without actually changing the array itself. As far as I can tell, to do so I need to used a constant version of the array in the function so the prototype would be something like: int *sortedCopy(const int *array, int size), but all this does is give the error shown in the title. Specifically:
main.cpp:72:29: error: assignment of read-only location '*(array +
((sizetype)(((long unsigned int)i) * 4)))' array[i] = array[min]
and it does this error twice, except with array[min] = temp; at the end instead
This is the code used, with the relevant parts of main:
#include <iostream>
using namespace std;
int* sortedCopy(const int *array, int size) {
int i, j, min, temp;
for (i = 0 ; i < size - 1; i++) {
min = i;
for (j = i + 1; j < size; j++) {
if (array[j] < array[min]) {
min = j;
}
}
temp = array[i];
array[i] = array[min];
array[min] = temp;
}
cout << "Sorted array is: " << endl;
for(int i = 0; i < size; i++) {
cout << array[i] << " ";
}
cout << endl;
// Not sure if I need to return anything or not either
}
int main() {
cout << "Please enter the size of the array." << endl;
int arraySize;
int array[arraySize];
cin >> arraySize;
cout << "Please enter integer values until the array is filled." << endl;
for (int i = 0; i != arraySize; i++) {
cout << "Value " << (i + 1) << ": ";
cin >> array[i];
cout << endl;
sortedCopy(array, arraySize);
for (int i = 0; i != arraySize; i++) { // I want this part to print the
cout << array[i] << " "; // original array entered by the user
}
}
If I remove the const part of the function, it works totally fine, except it will print the sorted array after the function is called, instead of the original array.
Firstly, C/C++ is best read "top-down":
int arraySize;
int array[arraySize]; // arraySize is undefined here!!
cin >> arraySize;
On the second line, ArraySize, might be 1, or 0, or -1000. You haven't defined it until line 3.
Also, C++ doesn't allow you to allocate arrays of variable size (unless that size is const [ so it is known at compilation time]):
int array[4];
The above is fine. This helps the operating system know how much memory to provide for you on the stack (it needs to do this before your programme starts running).
const int arraySize = 4;
int array[arraySize];
Because the C++ compiler knows that arraySize is 4, it processes this just like the above code, so this is also fine.
So to handle arrays of genuinely variable length (length that depends on inputs), you need to first read the user inputs, then use dynamic allocation ("new", or a container that does dynamic allocation for you, like a vector).
As for the problem with "const", what I think that you need to understand here is that "const" is really just a promise from the programmer: The programmer is communicating to the compiler (and any programmers reading the code) that this data is not supposed to change. All the compiler does is check whether you keep your promise (or if you send it to another function / pointer that doesn't hold that promise). So by using "const" there is no work done being done for you to actually keep the data constant - just that it will complain if you don't do the work.
int* sortedCopy(const int *array, int size) {
Above you're flagging to the compiler that the sortedCopy function will keep the data in the array constant.
array[i] = array[min];
array[min] = temp;
And here (above) you are breaking that promise.
If you don't want to edit the original array, then the easiest solution is just to copy it before you send it to your sorting function.
I am having issues de-allocating memory that I used in my char* array. In my code snippet below, I am creating a char* array named input that holds pointers to single words at a time followed by a pointerNULL at the end of the array. This is the only time (I believe) I allocate memory in my code.
char* input[999];
//exec commands
for(unsigned int i = 0; i < commands.size(); i++)
{
string current = "";
string word = "";
int k = 0;
for(unsigned int j = 0; j < commands.at(i).size(); j++) //iterate through letters
{
current = commands.at(i);
//cout << "current: " << current << endl;
if(current[j] == ' ')
{
input[k] = new char[word.size() + 1];
strcpy(input[k], word.c_str());
k++;
word = "";
}
else
word += current[j]; //add letter
//cout << "word: " << word << endl;
}
input[k] = new char[word.size() + 1];
strcpy(input[k], word.c_str());
k++;
input[k] = new char[1]; //add the NULL char *
input[k] = NULL;
...
Later on, I attempt to de-allocate this memory with this snippet of code:
for(int z = 0; z < k; z++)
{
delete[] input[z];
}
I am iterating through my char* array and deleting the memory allocated at each index. Without using this snippet, valgrind informs me of memory leaks. Using this snippet, valgrind informs me of less memory leaks than before. I am still stuck with the issue of memory still being definitely lost.
I am unsure what I am missing to remove the rest of the allocated memory (or if the cause of the rest of the memory leaks is in fact somewhere else in my code). I appreciate any and all help, suggestions, and tips.
I think, your problem is in below case,
input[k] = new char[1]; //add the NULL char *
input[k] = NULL;
here, without free-ing input[k], you're assigning NULL to it. Thus, the previous input[k] is lost.
If you really want input[k] to hold NULL, (maybe as a sentinel value), you can simply do
input[k] = NULL;
No need to allocate memory separately.
You don't need to create a new char on where it says input[k] = new char[1]; //add the NULL char * Just leave the NULL assignment in and it should work fine.
I'm hoping someone can shed some light on where I am going wrong with pointers.. I've read countless web pages and tried various things but for some reason my code is returning jibberish (which I'm guessing may be the memory addresses instead of the data within my array). The purpose of the program is to create an array of 100 elements on the heap, pass this array by a pointer to a function (along with two integer variables start and end); a new array will be created on the heap (this comprises of a chunk of the original array using the start and end variables) and the pointer to this array is passed back to the main method so that the new array can be outputted. My problem is not only is the output seeming to be the location not the value, but also it seems 100 values are outputted not 20 as should be expected. I've spent hours trying to figure out where I have gone wrong and just when I think I understand the concept of pointers my faith is destroyed by red squigglies and incorrect outputs. Please HELP! My code is as follows:
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
double* getSubArray(double*, int, int);// Declare a function that will get the sub array
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 100;// Declare the size of the array
double* pA;// Declare the variable to hold the pointers to the data in array
double* pB;
int start = 15;
int end = 35;
pA = new double[size];// Create space for the array
srand(clock());// Seed the program to the computers current time so that random gets a different set of random numbers everytime it is run
// Use a for loop to traverse through each element of the array (starting at index 0) placing a number defined by the random function that is no higher than 250
for (int i = 0; i < size; i++)
{
pA[i] = rand()%250;
}
cout << "An Array of 100 numbers is created and stored in the heap, these values are:" << endl;
// Output the Array for the user to see
for (int j = 0; j < size; j++)
{
// Place 10 numbers on each line
if (j % 10 == 0)
{
cout << endl;
}
cout << *(pA + j) << " ";
}
cout << endl << "The program will build a second array using the data between the indexes " << start << " & " << end << endl;
pB = getSubArray(pA, start, end);// Pass the data to the method
// Output second array for user to compare
for (int k = 0; k < size; k++)
{
// Place 10 numbers on each line
if (k % 10 == 0)
{
cout << endl;
}
cout << *(pB + k) << " ";
}
system("pause");
return 0;
}
double* getSubArray(double* pA, int start, int end)
{
double* pB = new double[end-start];// Declare space in the heap for the new array whoes size is the size of the criteria given
for (int i = 0; i < (end - start); i++)
{
for (int j = start; j < end; j++)
{
*(pB + 0) = pA[j];
}
}
return pB;
}
*(pB + 0) = pA[j];
That keeps writing to the first element of the array. Surely you want to write to each element in turn:
for (int i = start; i < end; ++i) {
pB[i-start] = pA[i];
}
or if you don't want to write your own loop
std::copy(pA+start, pA+end, pB);
Don't forget to delete[] everything you new[] or, to save mucking around with low-level memory management, use std::vector to manage the dynamic arrays for you.