Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

memory cannot be written

Status
Not open for further replies.

hugh7

Technical User
Mar 2, 2003
24
US
I'm using Visual C++ and
#include <iostream>
using namespace std;

I initialize a pointer to char at compile time with
char *can1[2]={&quot; &quot;} ;

If I try to write to it I get an error that the memory cannot be written
So then I tried getting new memory at runtime with

for (cnta=0; cnta<=2; cnta++)
can1[cnta]= new char[8] ;

This is great but if I output the new memory with cout I see garbage so I then
had the 'bright' idea to initialize the new memory like so

can1[cnta]=&quot; &quot;;

but after I do this I again get the error message, when I try to write to it, that the memory
cannot be written.

I sense that I'm missing something fundamental here.

Why can't I write to the array if I initialize it either at compile time or run time ?

If I don't initialize the new memory then I can overwrite the strings.


Just learning and trying to understand
Thanks for any ideas.

hugh
 
Code:
char* can1[2] = { &quot; &quot; };
declares array of two pointers to char array, not an array of char. The 2nd element initialized with null pointer. What for that initializations? It's useless...
Now your (incorrect) loop makes three new ops; right for is:
Code:
for (cnta = 0; cnta < 2; cnta++) // not <= !!!
...
can1[2] = ... oops: you are in trouble...
 
Hi ArkM

Thank you for your patience.
I want to declare an array of pointers to char which I will later fill from a text file. I'm not sure how to initialize it. In the code below the output is just some spaces. What's happening to what I type in?

//checkarr1

#include <iostream>
#include <fstream>

using namespace std;

char *ar1[2]={&quot; &quot;,&quot; &quot;}; //

int main()

{

cin>>*ar1[0] ;
cout<<*ar1[0]<<&quot; this is it &quot;<<endl;


return 0;
}

Here is my code for reading in from the text file:

//filestep2
#include <iostream> // read in
#include <fstream> // read out


using namespace std;
ifstream fsor;

int n;
char *myarray[35]={&quot; &quot;}; // AN array of //pointers to char only 1 ?
// is initialized
int cnta=0;

int main ()

{

fsor.open(&quot;c:\\copyback\\moveit1.txt&quot;); //HARD CODE OPEN SOURCE TEXT
while (fsor)

{

myarray[cnta]= new char[25];
fsor.getline(myarray[cnta],25,'\n') ;/// thisline compiled and displayed

if (strlen(myarray[cnta])>3)

cout <<myarray[cnta]<< &quot; This is line &quot;<< cnta<<endl;
cnta++;

}
// OUT PUT OF
cout<<strlen(myarray[1])<<&quot; This is hard coded lenght of myarray[1]&quot;<<endl;
fsor.close();

cout <<cnta << &quot; this is cnta&quot; << endl;
cout << *myarray<< endl; // outputs first array
cout <<n <<&quot; Number of lines&quot; << endl;

// RELEASE MEMORY //
int i;
for (i=0; i<=cnta; i++)
delete [] myarray[cnta];

return 0 ;

}

I'm not sure if this helps you get an idea of what I'm trying to do .

Thank again

Hugh
 
Dear Hugh7,
it seems I can imaginate what you want to do, but...

When you initialize ar1 (1st snippet) with pointers to string literals,
Code:
ar1[0] (and ar2[1])
refer to these (constant!) arrays of char with blanks, that's all. Now you read a line from cin into the 1st (constant!) array. If your (console or file) input has more than that constant length chars, you have a corrupted memory case. Never change string literals, it's C/C++ Standard violation!

If you need an array of pointers to char arrays
Code:
(char*[])
, you must initialize its elements with true (real;) arrays of char - for example, as you do it in 2nd snippet (but you code is not so clear as can be;). For example, do that:
Code:
const int Size = 25;
char* myarray[35]; // Don't initialize it here - do it later.
int i;
for (i = 0; i < 35; ++i)
    myarray[i] = new char[Size];
.... // Play with real 35 memory chunks...
for (i = 0; i < 35; ++i) // Don't forget deallocation
    delete [] myarray[i];
Well, you may allocate myarray elements step by step, as in your 2nd snippet. But your code is too dangerous: imagine 36 lines input (you don't check for cnta maximum value).

There are some another troubles in the 2nd snippet. You don't check bad open file condition (e.g. if (fsor)...). If fsor.getline() reads a long line (more than 24 chars), it set fail flag on fsor stream and can't read more lines until you clear this flag.

As you can see, low-level input into char arrays is not the best solution. Try std::string input (absolutely safe) targets. But it's the other story...

Good luck!
 
Oh, sorry (dumned TGML;), my snippet must be (w/o ?;):
for (i = 0; i < 35; ++i)
myarray = new char[Size];
.... // Play with real 35 memory chunks...
for (i = 0; i < 35; ++i) // Don't forget deallocation
delete [] myarray;
 
Hi ArkM
Thank you for your reply. Please pardon my ignorance but I'm not sure what you mean by &quot;refer to these (constant!) arrays of char with blanks&quot;,

I will use your suggestions for correcting my 2nd snippet. Could you give me a short example of using std::string input?

Thanks again

Hugh

 
A1:
Let's suppose we have:
Code:
char* a[2] = { &quot;  &quot;,&quot;  &quot; };
What we get (it's not a C++):
Code:
a[0] -> &quot;  &quot; - 3 bytes { 0x20, 0x20, 0 }
a[1] -> &quot;  &quot; - 3 bytes { 0x20, 0x20, 0 } may be in another place!
Compiler generates two (or one!) char[3] arrays, fills them with <blank><blank><null> codes and fills a[0] and a[1] with pointers to these arrays.

C++ Language declares that a compiler may generate the only one array for that text constant &quot; &quot; or two (or more) arrays for each its occurence: it's implementation-dependent issue.

Old C (not C++) does not treat string literals (e.g. &quot; &quot;) as constant values. But modern C (and C++) treats string literals as &quot;constants de facto&quot;: result of its modification is undefined (but type of &quot;...&quot; is char*, not const char*).

Moral: if you want 'true' read/write char memory, don't refer to string literals!

A2.
Use string C++ Standard library class to process text data (when possible).
Code:
#include <string>
#include <iostream>
using namespace std;
...
string str[10];
int n;
for (n = 0; n < 10 && (cout<<&quot;Enter string:&quot;,getline(cin,str[n]); ++n)
  ;
if (n)
{
  cout << n << &quot; strings echo:&quot; << endl;
  for (int k = 0; k < n; ++k)
    cout << str[k] << endl;
}
...
Class string objects can automatically allocate memory for your input lines. They automatically deallocate memory (destroy himself) in a proper time (not earlier).

If you want to play with string contents in C style, use c_str() member function, e.g.:
Code:
const char* p = arr[0].c_str();

But string class has a reach set of member functions to deal with string objects contents w/o old C-style functions from <cstring> header (C++ successor of old good <string.h>).

Good luck!
 
Hi ArkM,

Thanks again for the insight into the compiler. Its nice to know what's 'under' the hood, so to speak. I will study it.

I'm slowly progressing.
Is there a good site on line with info on the string library?

I need that 'good luck'

Hugh
 
In actual fact I wrote about language semantics, not about compilers background. We must understand specifications of our tools (i.e. programming languages).
The best source about C++ string (about C++ Language, I'm sure) is Bjarne Stroustrup's book The C++ Programming Language. It's true C++ programmer's handbook.
To say in all honesty, I don't read C++ manuals online. Try - sorry, I can't remember proper links now. Better read good books and think about...
 
I'll checkout codeguru and the Stroustrup book
Thanks

Hugh
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top