The function prints the addresses of each memory location of the dynamic array. Is this the right way?
int main()
{
char str[] = "This is a test";
printAddresses(str, strlen(str));
}
template <class type>
void printAddresses(type *item, int n)
{
cout << "Printing Addresses..." << endl;
for (int i = 0; i < n; i++)
{
cout << "Index " << i << ": " << ((&item) + i) << endl;
}
}
I've also heard that I should use:
cout << "Index " << i << ": " << (void*) &item[i] << endl;
but that gives me different memory address. I'm not sure which one is right.
The correct address is the one you obtain when printing (void*)&item[i].
item is already a pointer; so is &item[i]. You are interested in printing the value of this pointer, you need to cast it to void* before calling << on it.
When you print ((&item) + i) you are making an extra level of indirection (&item is a pointer-to-pointer), so you print the address of item-the-pointer, not the address of what item is pointing to.
Note:: Starting with C++11 you can use std::addressof function in place of operator & for better readability and to avoid potential issues when T provides an overload for operator &:
cout << "Index " << i << ": " << std::addressof(item[i]) << endl;
Run this:
#include <iostream>
#include <cstring>
using namespace std;
template <class type>
void printAddresses(type *item, int n)
{
cout << "Printing Addresses..." << endl;
for (int i = 0; i < n; i++)
{
cout << "Index " << i << ": " << ((&item) + i) << endl;
cout << "Index2 " << i << ": " << (void*) &item[i] << endl;
}
}
int main()
{
char str[] = "This is a test";
printAddresses(str, strlen(str));
}
which in my machine prints:
gsamaras#gsamaras-A15:~$ g++ -Wall main.cpp
gsamaras#gsamaras-A15:~$ ./a.out
Printing Addresses...
Index 0: 0x7ffd5c9ead58
Index2 0: 0x7ffd5c9ead90
Index 1: 0x7ffd5c9ead60
Index2 1: 0x7ffd5c9ead91
Index 2: 0x7ffd5c9ead68
Index2 2: 0x7ffd5c9ead92
Index 3: 0x7ffd5c9ead70
Index2 3: 0x7ffd5c9ead93
Index 4: 0x7ffd5c9ead78
Index2 4: 0x7ffd5c9ead94
Index 5: 0x7ffd5c9ead80
Index2 5: 0x7ffd5c9ead95
Index 6: 0x7ffd5c9ead88
Index2 6: 0x7ffd5c9ead96
Index 7: 0x7ffd5c9ead90
Index2 7: 0x7ffd5c9ead97
Index 8: 0x7ffd5c9ead98
Index2 8: 0x7ffd5c9ead98
Index 9: 0x7ffd5c9eada0
Index2 9: 0x7ffd5c9ead99
Index 10: 0x7ffd5c9eada8
Index2 10: 0x7ffd5c9ead9a
Index 11: 0x7ffd5c9eadb0
Index2 11: 0x7ffd5c9ead9b
Index 12: 0x7ffd5c9eadb8
Index2 12: 0x7ffd5c9ead9c
Index 13: 0x7ffd5c9eadc0
Index2 13: 0x7ffd5c9ead9d
Now think what sequence you expect to see for stored chars? You expect every character to be adjacent to the previous one (of course) and every one to take 1 memory cell. That should tell you that:
(void*) &item[i]
is the right thing to do.
Also notice that zmbq's comment, about using a debugger to find out makes sense too.
Finally, I would advice you to read: Printing array element memory adresses C and C++, why different output?
A possible way could be to use the C-style printf with %p. So include <cstdio> then try for example:
const char *sp = "abcde" + 2; // some computation giving a string address
printf("sp=%p ('%s')\n", sp, sp);
Alternatively, cast to (void*) and use usual
std::cout << "sp at " << (void*)sp << std::endl;
The reason you get a different memory address is because your code is wrong.
void printAddresses(type *item, int n)
item is a pointer parameter to your printAddresses template function. So, in the following expression:
cout << "Index " << i << ": " << ((&item) + i) << endl;
Therefore:
&item
becomes the address of the parameter to your template function, and not the address of the array.
This is why:
(&item)+i
is wrong, and is utterly meaningless. The address of the parameter to your template function is not really very useful, here.
(void*) &item[i]
Is the correct answer.
Related
I wrote a text cipher program. It seems to works on text strings a few characters long but does not work on a longer ones. It gets the input text by reading from a text file. On longer text strings, it still runs without crashing, but it doesn’t seem to work properly.
Below I have isolated the code that performs that text scrambling. In case it is useful, I am running this in a virtual machine running Ubuntu 19.04. When running the code, enter in auto when prompted. I removed the rest of code so it wasn't too long.
#include <iostream>
#include <string>
#include <sstream>
#include <random>
#include <cmath>
#include <cctype>
#include <chrono>
#include <fstream>
#include <new>
bool run_cypher(char (&a)[27],char (&b)[27],char (&c)[11],char (&aa)[27],char (&bb)[27],char (&cc)[11]) {
//lowercase cypher, uppercase cypher, number cypher, lowercase original sequence, uppercase original sequence, number original sequence
std::ifstream out_buffer("text.txt",std::ios::in);
std::ofstream file_buffer("text_out.txt",std::ios::out);
//out_buffer.open();
out_buffer.seekg(0,out_buffer.end);
std::cout << "size of text: " << out_buffer.tellg() << std::endl;//debug
const int size = out_buffer.tellg();
std::cout << "size: " << size << std::endl;//debug
out_buffer.seekg(0,out_buffer.beg);
char *out_array = new char[size + 1];
std::cout << "size of out array: " << sizeof(out_array) << std::endl;//debug
for (int u = 0;u <= size;u = u + 1) {
out_array[u] = 0;
}
out_buffer.read(out_array,size);
out_buffer.close();
char original[size + 1];//debug
for (int bn = 0;bn <= size;bn = bn + 1) {//debug
original[bn] = out_array[bn];//debug
}//debug
for (int y = 0;y <= size - 1;y = y + 1) {
std::cout << "- - - - - - - -" << std::endl;
std::cout << "out_array[" << y << "]: " << out_array[y] << std::endl;//debug
int match;
int case_n; //0 = lowercase, 1 = uppercase
if (isalpha(out_array[y])) {
if (islower(out_array[y])) {
//std::cout << "out_array[" << y << "]: " << out_array[y] << std::endl;//debug
//int match;
for (int ab = 0;ab <= size - 1;ab = ab + 1) {
if (out_array[y] == aa[ab]) {
match = ab;
case_n = 0;
std::cout << "matched letter: " << aa[match] << std::endl;//debug
std::cout << "letter index: " << match << std::endl;//debug
std::cout << "case_n: " << case_n << std::endl;//debug
}
}
}
if (isupper(out_array[y])) {
for (int cv = 0;cv <= size - 1;cv = cv + 1) {
if (out_array[y] == bb[cv]) {
case_n = 1;
match = cv;
std::cout << "matched letter: " << bb[match] << std::endl;//debug
std::cout << "letter index: " << match << std::endl;//debug
std::cout << "case_n: " << case_n << std::endl;//debug
}
}
}
if (case_n == 0) {
out_array[y] = a[match];
std::cout << "replacement letter: " << a[match] << " | new character: " << out_array[y] << std::endl;//debug
}
if (case_n == 1) {
std::cout << "replacement letter: " << b[match] << " | new character: " << out_array[y] << std::endl;//debug
out_array[y] = b[match];
}
}
if (isdigit(out_array[y])) {
for (int o = 0;o <= size - 1;o = o + 1) {
if (out_array[y] == cc[o]) {
match = o;
std::cout << "matched letter: " << cc[match] << std::endl;//debug
std::cout << "letter index: " << match << std::endl;//debug
}
}
out_array[y] = c[match];
std::cout << "replacement number: " << c[match] << " | new character: " << out_array[y] << std::endl;//debug
}
std::cout << "- - - - - - - -" << std::endl;
}
std::cout << "original text: " << "\n" << original << "\n" << std::endl;
std::cout << "encrypted text: " << "\n" << out_array << std::endl;
delete[] out_array;
return 0;
}
int main() {
const int alpha_size = 27;
const int num_size = 11;
char l_a_set[] = "abcdefghijklmnopqrstuvwxyz";
char cap_a_set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char n_a_set[] = "0123456789";
std::cout << "sizeof alpha_set: " << std::endl;//debug
char lower[alpha_size] = "mnbvcxzasdfghjklpoiuytrewq";
char upper[alpha_size] = "POIUYTREWQASDFGHJKLMNBVCXZ";
char num[num_size] = "9876543210";
int p_run; //control variable. 1 == running, 0 == not running
int b[alpha_size]; //array with values expressed as index numbers
std::string mode;
int m_set = 1;
while (m_set == 1) {
std::cout << "Enter 'auto' for automatic cypher generation." << std::endl;
std::cout << "Enter 'manual' to manually enter in a cypher. " << std::endl;
std::cin >> mode;
std::cin.ignore(1);
std::cin.clear();
if (mode == "auto") {
p_run = 2;
m_set = 0;
}
if (mode == "manual") {
p_run = 3;
m_set = 0;
}
}
if (p_run == 2) { //automatic mode
std::cout <<"lower cypher: " << lower << "\n" << "upper cypher: " << upper << "\n" << "number cypher: " << num << std::endl;//debug
run_cypher(lower,upper,num,l_a_set,cap_a_set,n_a_set);
return 0;//debug
}
while (p_run == 3) {//manual mode
return 0;//debug
}
return 0;
}
For example, using an array containing “mnbvcxzasdfghjklpoiuytrewq” as the cipher for lower case letters, I get “mnbv” if the input is “abcd”. This is correct.
If the input is “a long word”, I get “m gggz zzzv” as the output when it should be “m gkjz rkov”. Sort of correct but still wrong. If I use “this is a very very long sentence that will result in the program failing” as the input, I get "uas” as the output, which is completely wrong. The program still runs but it fails to function as intended. So as you can see, it does work, but not on any text strings that are remotely long. Is this a memory problem or did I make horrible mistake somewhere?
For your specific code, you should run it through a memory checking tool such as valgrind, or compile with an address sanitizer.
Here are some examples of memory problems that most likely won't crash your program:
Forgetting to delete a small object, which is allocated only once in the program. A memory leak can remain undetected for decades, if it does not make the program run out of memory.
Reading from allocated uninitialized memory. May still crash if the system allocates objects lazily at the first write.
Writing out of bounds slightly after an object that sits on heap, whose size is sizeof(obj) % 8 != 0. This is so, since heap allocation is usually done in multiples of 8 or 16. You can read about it at answers of this SO question.
Dereferencing a nullptr does not crash on some systems. For example AIX used to put zeros at and near address 0x0. Newer AIX might still do it.
On many systems without memory management, address zero is either a regular memory address, or a memory mapped register. This memory can be accessed without crashing.
On any system I have tried (POSIX based), it was possible to allocate valid memory at address zero through memory mapping. Doing so can even make writing through nullptr work without crashing.
This is only a partial list.
Note: these memory problems are undefined behavior. This means that even if the program does not crash in debug mode, the compiler might assume wrong things during optimization. If the compiler assumes wrong things, it might create an optimized code that crashes after optimization.
For example, most compilers will optimize this:
int a = *p; // implies that p != nullptr
if (p)
boom(p);
Into this:
int a = *p;
boom(p);
If a system allows dereferencing nullptr, then this code might crash after optimization. It will not crash due to the dereferencing, but because the optimization did something the programmer did not foresee.
This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
Closed 4 years ago.
I know how to pass 1D array pointer to a function by the following code
void fiddleWithArray(int*);
int main(){
int list[10] = {1, 3, 5, 7, 9, 11, 13, 17};
cout << "List at 0 before being passed is... " << list[0][0] << endl;
cout << "List at 1 before being passed is... " << list[1][0] << endl;
fiddleWithArray(list);
cout << "List at 0 after being passed is... " << list[0][0] << endl;
cout << "List at 1 after being passed is... " << list[1][0] << endl;
}
void fiddleWithArray(int* input){
input[0] = 45;
input[1] = 18;
}
However, when I try to do something similar for a 2D array(as shown below) I get an error.
void fiddleWithArray (int** input);
int main ()
{
int list [10][2]={{1,3},{5,7},{9,11},{13,17},{7,4},{5,90},{9,1},{3,25}};
int ** pointer;
pointer=&list;
cout<< "List at 0 before being passed is ... "<< list[0][0]<< endl;
cout<< "List at 1 before being passed is ... "<< list[1][0]<< endl;
fiddleWithArray(pointer);
cout<< "List at 0 after being passed is ... "<< list[0][0]<< endl;
cout<< "List at 1 after being passed is ... "<< list[1][0]<< endl;
}
void fiddleWithArray(int** input)
{
cout << input [6][1]<< endl;
}
The compiler gives an error saying "error: cannot convert ‘int (*)[10][2]’ to ‘int**’ in assignment
pointer=&list;"
I am also open to alternate methods of passing a 2D array pointer to a function.
Keeping your data structure, if you want to pass list to fiddleWithArray you can declare it as
void fiddleWithArray (int input[][2]);
and then, in the main program, call it as
fiddleWithArray(list);
There is also another problem in your program: cout << list[0] does not work. If you want to print the contents of the array when the first index is fixed to 0 you would write something like
cout << list[0][0] << " " << list[0][1]
If you instead intended to write the array where the second index is fixed to 0 or 1, then, to keep things easily, you need a short loop like
for (unsigned int i = 0; i < 10; i++)
cout << list[i][0] << " ";
cout << endl;
Finally, instead of using int[][] you may want to use std::arrayintroduced in C++11.
void fiddleWithArray(int input[10][2])
{
cout << input[6][1] << endl;
}
int main()
{
int list[10][2] = {{1,3},{5,7},{9,11},{13,17},{7,4},{5,90},{9,1},{3,25}};
int (*pointer)[10][2];
pointer=&list;
cout << "List at 0 before being passed is ... "<< list[0][0]<< endl;
cout << "List at 1 before being passed is ... "<< list[1][0]<< endl;
fiddleWithArray(*pointer);
cout << "List at 0 after being passed is ... "<< list[0][0]<< endl;
cout << "List at 1 after being passed is ... "<< list[1][0]<< endl;
}
Will be better using std::array
Here's the code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int keyArray[7] = {1,2,3,4,5,6,7};
int breakPoint;
int counter;
for (counter = 0; counter < 7; counter++)
{
// keyArray[counter] = (rand() % 9) + 1; later
keyArray[counter] = counter; //testing
}
cout << keyArray[0] + "\n";
cout << keyArray[1] + "\n";
cout << keyArray[2] + "\n";
cout << keyArray[3] + "\n";
cout << keyArray[4] + "\n";
cout << keyArray[5] + "\n";
cout << keyArray[6] + "\n";
cin >> breakPoint; //so I can see what the hell is going on before it disappears
return 0;
}
The only reason I gave values to keyArray was that I read in answer to a similar question that you have to initialize an array with data before you use it. But it made no difference. The output is just junk symbols whether you initialize or not.
The compiler is Visual Studio Community 2017. Thanks for any help.
The error is not in your logic but rather in your debugging output. Since the other answers focus on how to fix it, I'll rather explain what happens instead. There seems to be a misunderstanding about the way strings work in C++.
The failure is in this operation:
keyArray[0] + "\n"
Internally, string literals are arrays of characters, in this case const char[2], consisting of the newline and a terminating '\0' null terminator. When you then try to add the integer and this array together, the array will be represented by a pointer to its first element, i.e. it will decay to const char* in order to be used as the second argument to the plus operator used in your code.
So for the compiler, this line will need operator+(int, const char*). But the result of that will be const char*, the input pointer offset by the integer, as that is the operation that happens when adding integers to pointers.
So instead of printing the number and then the string, it will try to access a string that does not exist as the pointer now pointer behind the string "\n" and thus into some arbitrary memory.
Instead of doing
cout << keyArray[0] + "\n"
do:
cout << keyArray[0] << "\n"
or
cout << keyArray[0] << endl
You can't concatanate an integer with a string. That's why you got garbage output
Try this first:
cout << keyArray[0] << "\n";
If you are using compilers that support C++ 11 then try using std::to_string(...) to make a string from an integer before doing the addition:
cout << (std::to_string(keyArray[0]) + "\n");
you cannot concatenate int with string.
change
cout << keyArray[0] + "\n";
cout << keyArray[1] + "\n";
cout << keyArray[2] + "\n";
cout << keyArray[3] + "\n";
cout << keyArray[4] + "\n";
cout << keyArray[5] + "\n";
cout << keyArray[6] + "\n";
to
cout << keyArray[0] << "\n"
<< keyArray[1] << "\n"
<< keyArray[2] << "\n"
<< keyArray[3] << "\n"
<< keyArray[4] << "\n"
<< keyArray[5] << "\n"
<< keyArray[6] << endl;
You need to convert the integers into a string. Using a relatively recent version of C++:
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
int keyArray[7] = {1,2,3,4,5,6,7};
int breakPoint;
int counter;
for (counter = 0; counter < 7; counter++)
{
// keyArray[counter] = (rand() % 9) + 1; later
keyArray[counter] = counter; //testing
}
cout << std::to_string(keyArray[0]) + "\n";
cout << std::to_string(keyArray[1]) + "\n";
cout << std::to_string(keyArray[2]) + "\n";
cout << std::to_string(keyArray[3]) + "\n";
cout << std::to_string(keyArray[4]) + "\n";
cout << std::to_string(keyArray[5]) + "\n";
cout << std::to_string(keyArray[6]) + "\n";
cin >> breakPoint; //so I can see what the hell is going on before it disappears
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
class Foo
{
public:
virtual void f1()
{
cout << "Foo::f1()" << endl;
}
virtual void f2()
{
cout << "Foo::f2()" << endl;
}
virtual void f3()
{
cout << "Foo::f3()" << endl;
}
};
int main()
{
typedef void(*MethodFoo_f)();
Foo* ptr = new Foo();
cout << "Object address: " << ptr << endl;
cout << "__vfptr: " << (int*)*((int*)ptr) << endl;
for(int i = 0; i < 3; ++i)
{
int* e = (int*)*((int*)ptr) + i;
cout << "Address from __vfptr " << e;
auto t = &Foo::f1;
switch(i)
{
case 0: t = &Foo::f1; cout << ", address from main " << (void*&)t << " "; break;
case 1: t = &Foo::f2; cout << ", address from main " << (void*&)t << " "; break;
case 2: t = &Foo::f3; cout << ", address from main " << (void*&)t << " "; break;
}
cout << "execute: ";
auto func = (MethodFoo_f*)(e);
(*func)();
}
}
Hi all, can you explain me: why we can see difference in addresses of same method's.
Example output for Visual Studio
Object address: 007ADE28
__vfptr: 00E63B34
Address from __vfptr 00E63B34, address from main 00E51F23 execute:
Foo::f1()
Address from __vfptr 00E63B38, address from main 00E51F1E execute:
Foo::f2()
Address from __vfptr 00E63B3C, address from main 00E51F19 execute:
Foo::f3()
If VTABLE call transforme to
objPointer->(__vfptr + methodIndex)()
Why in table, we hold modified values of addresses ?
I finally realized what you wanted, you are missing one level of indirection.
ptr points to the object
(assuming 32 bit and many other things you shouldn't really assume):
*((int*)ptr) is the address of the vtable
(int*)*((int*)ptr) is *((int**)ptr) is a cast of that same address
(int*)*((int*)ptr)+i is & (*((int**)ptr))[i] is a position within the vtable and you wanted the contents of that position:
*((int*)*((int*)ptr)+i) or (*((int**)ptr))[i]
You have that extra level of indirection instead in func
MethodFoo_f is the type of a pointer to the function and func is a pointer to MethodFoo_f
So the numbers you expect to be the same for each function were a pointer to pointer to function and a simple pointer to function.
I still wouldn't guess the pointer to function you get from auto t = &Foo::f1; reliably has the same contents as a void* to the actual code of the function. But at least with the correct levels of indirection you would be comparing it to that.
This question already has answers here:
Pointer errors in the method of transmission(c++)
(4 answers)
Closed 8 years ago.
Question: I can't seem to set a pointer to an address that was created inside of a function. It always gets set to Null, how do I fix this?
Problem: I believe the problem is caused by the variable being created inside of another function. What's happening is that after the function executes, the pointer is set to NULL again.
Code:
void listAdd(int *list, int &length) {
int* tempList = new int[ length + 1 ];
for( int i = 0; i < length; i ++ )
{
(tempList)[ i ] = (list)[ i ];
}
cout << " Previous adress: " << hex << list << endl;
if ( list != NULL )
delete[] list;
list = new int[ length + 1 ];
cout << " New address: " << hex << list << endl << dec;
for( int i = 0; i < length; i ++ )
{
(list)[ i ] = (tempList)[ i ];
}
delete[] tempList;
cout << " Enter a number: ";
int stored = 0;
cin >> stored;
(list)[length -1] = stored;
length ++;
cout << " Length: " << length << "\n";
cout << " value at array point 0: " << (list)[length -1];
cout << "\n retry " << (list)[length-1] <<"\n";
cout << "\n \n \n This is pointing to 0x" << hex << list << '\n' << flush;
}
It seems you would like the changes to list to be valid after the function returned: since list is passed by value, the object manipulated inside the function happens to be a copy of the one you passed in. You probably either want to pass the object by reference, i.e.:
void listAdd(int*& list, int &length) {
// ...
}
... or return the result
int* listAdd(int* list, int& length) {
// ...
return list;
}
list = listAdd(list, length);
Well, realistically, you really really want to encapsulate the objects in a class or just use std::vector<int>.