Error reading characters of string c

I have the following block of code: for( CarsPool::CarRecord &record : recs->GetRecords()) { LVITEM item; item.mask = LVIF_TEXT; item.cchTextMax = 6; item.iSubItem = 0; item.pszT...

I have the following block of code:

for( CarsPool::CarRecord &record : recs->GetRecords())
{
  LVITEM item;
  item.mask = LVIF_TEXT;
  item.cchTextMax = 6;

  item.iSubItem = 0;
  item.pszText = (LPSTR)(record.getCarName().c_str()); //breakpoint on this line.
  item.iItem = 0;
  ListView_InsertItem(CarsListView, &item);

  item.iSubItem = 1; 
  item.pszText = TEXT("Available");
  ListView_SetItem(CarsListView, &item);

  item.iSubItem = 2;
  item.pszText = (LPSTR)CarsPool::EncodeCarType(record.getCarType());
  ListView_SetItem(CarsListView, &item);
}

The information from Visual Studio Debugger is here:

enter image description here

Why isn’t the program able to read the characters from string?

A test has shown me that it works in this way:

MessageBox(hWnd, (LPSTR)(record.getCarName().c_str()), "Test", MB_OK);

asked Sep 22, 2013 at 17:07

Victor's user avatar

3

getCarName likely returns a temporary. After the assignment the temporary object is destroyed and the pointer item.pszText points to invalid memory. You must ensure that the string object is valid during the call to ListView_InsertItem.

std::string text(record.getCarName());
item.iSubItem = 0;
item.pszText = const_cast<LPSTR>(text.c_str());
item.iItem = 0;
ListView_InsertItem(CarsListView, &item);

The const_cast is an artifact of the fact that the Windows API uses the same structure to set and retrieve information. When invoking ListView_InsertItem the structure is immutable, however there is no way to reflect that in the language.

answered Sep 22, 2013 at 17:26

IInspectable's user avatar

IInspectableIInspectable

44.7k8 gold badges84 silver badges176 bronze badges

1

It looks like you’re trying to use the value of a C++ «string» in a C/Win32 call.

stdstring.c_str() is the correct way to do it.

… BUT …

You should strcpy() the string to a temp variable, then make the Win32 call with the temp variable.

answered Sep 22, 2013 at 17:18

paulsm4's user avatar

paulsm4paulsm4

112k16 gold badges135 silver badges187 bronze badges

1

  • Forum
  • General C++ Programming
  • Error Reading Characters of String

Error Reading Characters of String

I am currently using command line inputs in conjunction with several hardware inputs from my io ousb board…

I am trying to execute code where my second command-line argument, ‘c1′ ,’c2’ ‘c3’ or ‘c4’ executes the next part of my code that I’ve written. However, when I run the code, It only reads ‘c’, not ‘c1’. Through debugging, it says there is an error in reading the characters of the string.

below is a segment of my code:

if (argc == 3)
{
char * choice = argv[2];

//cout << argv[2][0] << endl;
if (choice == «C1»)
{
if (ReadPinC() > PortADC())
{
mainResult = ReadPinC();
printBinaryReverse(check_result(mainResult));
WritePortB(check_result(mainResult));
}
else if (PortADC() > ReadPinC())
{
mainResult = PortADC();
printBinaryReverse(check_result(mainResult));
WritePortB(check_result(mainResult));
}
return 0;
}

else if (choice == «c2»)
{

Make

choice

a

std::string

if you want to compare with ==

Thanks, could you explain to me why this is so? I’m still fairly new to c++ and coding in general

Each operator, like ==, has to be defined for its operands and no such operation is built into the standard for C-strings (your char[] arrays): for those you could use the strcmp() function to compare two C-strings, but it is more messy.

std::string is a well-defined class to hold character sequences that behaves naturally and has comparison-for-equality operations (==) defined for it, as well as the convenience of building up strings with a + operation.

For more detail see:
http://www.cplusplus.com/reference/string/string/

Note that we can only see a few lines of your code, so it is not easy to comment, and you don’t give the actual error message. It would also help if you put your code in code tags (first item on the format menu), as this would preserve indentation etc. and, for runnable code, allow us to compile and run it in an online shell.

Topic archived. No new replies allowed.

Hello.

I’m a CS student and taking C++ class.

This is my first question and I hope this put me on a good start in MSDN community. :)

I’m doing a homework experimenting with class hierarchy and data structures of bag and set.

I finally don’t have compile errors but runtime errors.

The error details are as follows:

Unhandled exception at 0x00DB6577 in Assignment06.exe: 0xC0000005: Access violation reading location 0xDDDDDDDD.

As I debug the break indicated this part of the code in the file Container.cpp :

Bag::~Bag() {
	cout << "deleting the bag" << endl;
	delete[] container;
}

with following details:

+ container
0x00ea946c {name=0xdddddddd <Error reading characters of string.> age=-572662307 }
Person *
+ this
0x00d7fbdc {size=1 capacity=10 container=0x00ea946c {name=0xdddddddd <Error reading characters of string.> …} }
Bag *

And the following is the whole code associated with this run.

// Container.h
#include "Person.h"
#define DEFAULT_CAP 50

class Bag
{
public:
	Bag(int capacity = DEFAULT_CAP);
	~Bag();
	void Add(Person p);
	Person* Delete();
	bool isEmpty() const;
	bool isFull() const;
	int currentSize() const;
	int Capacity() const;
	void Full();
	void Empty();

protected:
	int size;
	int capacity;
	Person* container;
};

class Set : public Bag
{
public:
	Set(int capacity = DEFAULT_CAP);
	~Set();
	void Add(Person p);
};
// Container.cpp

#include "Container.h"
#include <iostream>
#include <stdlib.h>
using namespace std;

// Bag class methods

Bag::Bag(int max_capacity) {
	cout << "constructing the bag" << endl;
	capacity = max_capacity;
	size = 0;
	container = new Person[capacity];
}

Bag::~Bag() {
	cout << "deleting the bag" << endl;
	delete[] container;
}

void Bag::Add(Person p) {
	if (isFull())
		Full();
	else 
		container[size++] = p;
}

Person* Bag::Delete() {
	if (isEmpty()) {
		Empty();
		return NULL;
	}
	else {
		//generate a random number between 0 and (size - 1)
		int index = (int) rand() % size;
		Person* p = &container[index];
		container[index] = container[size - 1];
		size--;
		return p;
	}
}

bool Bag::isEmpty() const { return (size == 0); }

bool Bag::isFull() const { return (size == capacity); }

int Bag::currentSize() const { return size; }

int Bag::Capacity() const { return capacity; }

void Bag::Full()
{
	cout << "The container is full" << endl;
}

void Bag::Empty()
{
	cout << "The container is empty" << endl;
}


// Set class methods


Set::Set(int max_capacity) : Bag(max_capacity) {
	cout << "constructing the set" << endl;
}

Set::~Set() {
	cout << "deleting the set" << endl;
	delete[] container;
}

void Set::Add(Person p) {
	for (int i = 0; i < size; i++){
		if (container[i] == p){
			cout << "This person is already in the set" << endl;
			return;
		}
	}
	
	if (isFull())
		Full();
	else
		container[size++] = p;
}
// Person.h
#include <iostream>
#include <string>
using namespace std;

class Person
{
protected:
	char* name;
	int age;
public:
	Person() {}
	Person(char* n, int a) : name(n), age(a) 
	{
		cout << "I'm " << name << ", aged " << age << "." << endl;
	}
	virtual ~Person() {}
	char* Name() { return name; }
	int Age() { return age; }
	bool Person::operator == (const Person& other) const {
		if (strcmp(name, other.name) == 0 && age == other.age)
			return true;
		return false;
	}
};

class Employee : public Person
{
protected:
	char* position;
	int pay;
public:
	Employee() {}
	Employee(char* pos, int p) : position(pos), pay(p) {}
	virtual ~Employee() {}
	char* Position() { return position; }
	int Pay() { return pay; }
	void setPosition(char* c) { position = c; }
	void setPay(int i) { pay = i; }
};

class Student : public Person
{
protected:
	int s_num;
	char* major;
public:
	Student() {}
	Student(int s, char* m) : s_num(s), major(m) 
	{
		cout << "Student number : " << s_num << " ; major : " << major << endl;
	}
	virtual ~Student() {}
	int sNum() { return s_num; }
	char* Major() { return major; }
	void setSNum(int i) { s_num = i; }
	void setMajor(char* c) { major = c; }

	bool Student::operator == (const Student& other) const {
		if (s_num == other.s_num)
			return true;
		return false;
	}
};

class gradStudent : public Student 
{
protected:
	char* concentration;
public:
	gradStudent() {}
	gradStudent(char* c) : concentration(c) {}
	virtual ~gradStudent() {}
	char* Concentration() { return concentration; }
	void setConcentration(char* c) { concentration = c; }
};

class StudentWorker : public gradStudent, Employee
{
protected:
	int regist_num;
public:
	StudentWorker() {}
	virtual ~StudentWorker() {}
	int RegistNum() { return regist_num; }
	void setRegistNum(int i) { regist_num = i; }
};

class phdStudent : public gradStudent
{
public:
	phdStudent() {}
	phdStudent(Person(char* name, int age), Student(int sn, char* m), char* c) 
	{ 
		concentration = c; 
		cout << "I'm a PhD. Student concentrating on " << concentration << endl;
	}
	~phdStudent() {}

};

class phdWorker : public StudentWorker
{
protected:
	char* company;
public:
	phdWorker(Person(char* n, int a), Student(int sn, char* m), char* c)
	{
		company = c;
		cout << "I'm a PhD. student working for " << company << endl;
	}
	~phdWorker() {}
};

and the main

#include <iostream>
#include "Container.h"
using namespace std;

void main()
{
	Bag phdStds(10);
	Set phdWorks(10);

	cout << "Bag capacity : " << phdStds.Capacity() << endl;
	cout << "Set capacity : " << phdWorks.Capacity() << endl;

	phdStds.Add(Person("John", 11));
	phdWorks.Add(Person("Scala", 27));

}

As I give several variations to the codes, now I’m almost sure that the problem is happening when destructors are called. 

I learned some new things as follows:

  • 0xDDDDDDDD Used
    by MicroQuill’s SmartHeap and Microsoft’s C++ debugging heap to mark freed heap memory

But…. still this puzzle is out of my reach.

Please give me suggestions, concerns, and corrections as they come to you.

Thank you very much.

  • Moved by

    Saturday, June 7, 2014 5:37 PM

  • Moved by
    Dave PatrickMVP
    Saturday, June 7, 2014 7:14 PM

About a week ago I was working on a Programming Challenge. The debugger was running, and the only breakpoint was set on a string member variable. Hovering over the [allocator] section to see what was going, things changed dramatically. An error message?

_Ptr = 0x325785 <Error reading characters of string.>  

What is going on here? Have I done something wrong? Is it some problem with Visual Studio? Could it be a component of my security suite that is causing this error? Whatever it was, why was the program running and compiling and building just fine? Why was the output as expected? Why didn’t the program freeze or crash if there is indeed an error?

My best bet seemed to be to look this error up on the Internet. To my surprise the results matching my search were sparse. Microsoft does seem to be aware that the error exists, but no bugfix or solution seems to exist for it. One of the few solutions I found didn’t work either: «Disable all Optimizations in the project properties. (Alt + F7), C/C++, Optimizations and Linker, Optimizations.» 

I was left to my own devices to solve the problem … Starting up VS, setting up a new project, toying around with the project settings, trying a different framework, nothing helped. Next I was loading some of my old projects to see whether this problem occurs or doesn’t and it did. Days went by without getting any closer to the root of the problem or finding a solution for it, I decided to wipe my system. With a clean installation of both the OS and VS my hope was that things would take a turn for the better. They did not …

Back on square one I had two options:

One: Ignore it. Impossible … 

Two: Trying my luck on finding a solution Online once more, …

Before going Online, I set up another project in VS:

#include <string>
#include <iostream>

int main()

{
    std::string myLittlePonyOne = «Rarity»;
    std::string myLittlePonyTwo = «Twilight Sparkle»;

    std::cout << «My favorite My Little Pony Characters are:n»
                  << myLittlePonyOne << » n»
                  << myLittlePonyTwo << » n»;

    std::cin.ignore();
    return 0;
}

I didn’t debug it right away, else I would have discovered that this little program contains the solution to the problem. Had I done it without looking for a solution, I wouldn’t have found the answer to the question why this error was occurring and what was causing it. Here is the ‘solution’ or rather answer to the problem.

The STL string classes contain an optimization called Small String Optimization or SSO for short. To learn more about it, please visit Giovanni Dicanio’s C++ Corner on the Internet. Having read this blog-post, I immediately went back to the IDE, started the debugger, and found that this was the source of the ‘error’. Consider the following screenshots:

As «Rarity» is very short, it is a small variable, so there is
no memory allocated on the heap, resulting in this ‘error’ message. 

Not so in case of «Twilight Sparkle», which is long enough, resulting in correct behavior. 

After carrying out some more tests just to be sure I found that this was indeed the source of the ‘error’ that is anything but. «It’s not a bug, it’s a feature», or in this case «It’s not a bug, it’s an optimization», to coin a new phrase. I’m just glad that in the end it turned out that all of my programs old and new containing string class in the end turn out not to be error-ridden.  

I sincerely hope that none of my readers, much less my fellow learners, will have to go through so much trouble … With this, I wish my readers and fellow learners a successful new week, and thank you very much for your visit and continued interest in this modest blog. As for me, it is time to write more code, and to overcome more errors and bugs.

Я пытаюсь сохранить значение из

vector<vector<string>> data;

в переменную const char *, объявленную в файле .h, следующим образом:

heightmapName = data[0][1].c_str();

Когда я отлаживаю программу, я замечаю, что переменная heightmapName вернуть это

heightmapName 0xcdcdcdcd <Error reading characters of string.>  const char *

Однако, если я объявлю новый const char* и инициализировать это так:

    const char* what = data[0][1].c_str();
heightmapName = data[0][1].c_str();

what переменная хранит данные просто отлично, в то время как heightmapNameне делает.

Это функция:

void Configuration::fileParser(string fileName)
{
vector<vector<string>> data;
string line;
string delimiter = " ";
ifstream ss(fileName);
if (ss)
{
while (getline(ss, line))
{
vector<string> dataLine;
string token = line.substr(0, line.find(delimiter));
string value = line.substr(line.find(delimiter) +1);
dataLine.push_back(token);
dataLine.push_back(value);
data.push_back(dataLine);
}
ss.close();
}
//storeData(data);
const char* ahah = data[0][1].c_str();
heightmapName =    data[0][1].c_str();
}

Почему это происходит? и как я могу решить это?

пс. Я использую Visual Studio 2017

-1

Решение

Независимо от проблемы или реализации, предполагая, что тип heightmapName это действительно const char *это не сработает.

Время жизни data ограничен временем жизни fileParser. Увидеть Что такое время жизни std :: string :: c_str ()?

Следовательно, в конце этой функции данные, указанные data[0][1].c_str() станет недействительным.

Попробуйте скопировать данные, если это необходимо. Или сделайте heightmapName как std :: string.

(Дополнительные советы: если это указатель, подумайте о применении правила пяти: Как на самом деле реализовать правило пяти? — еще одна причина избегать ручного управления памятью)

В общем, я избегаю необработанных указателей в классах C ++, используя умные указатели или структуры (такие как std :: string), которые управляют памятью для меня, это означает, что мне не нужно беспокоиться о правиле 3 или правиле 5, так как я не нужно вручную управлять этими ресурсами.

обновление: вы упомянули, что он «работает» для вас в (теперь удален) сущности.

Такой доступ к памяти после окончания жизни не определен. Одним поведением вполне может быть то, что оно волшебным образом «работает». Скорее всего, эта память просто еще не была перезаписана.

1

Другие решения

Других решений пока нет …

The data member reasons of the structure reasonList is an array of pointers of the type char *.

char* reasons[MAX_LIST_LENGTH];

So the first argument of this call of fgets

fgets(&list->reasons[index], STR_LEN, stdin);

has the type char ** while the function expects an argument of the type char *. So this call invokes undefined behavior.

Also from the presented code it is unclear whether these pointers (elements of the array) point to character arrays. If you did not allocate dynamically character arrays to which the pointers will point then if you will even write correctly

fgets( list->reasons[index], STR_LEN, stdin); 

nevertheless such a call again will invoke undefined behavior.

Taking into account the error message it seems you indeed forgot to allocate character arrays that would be pointed to by the elements (pointers) of the array.

Take into account that the function fgets can append the new line character 'n' to entered strings that you should remove.

The function could look for example the following way

int addReason( reasonList *list )
{
    int success = list->numReasons < MAX_LIST_LENGTH;
 
    if ( success )
    {
        list->reasons[list->numReasons] = malloc( STR_LEN );
        success = list->reasons[list->numReasons] != NULL;

        if ( success )
        {
            list->reasons[list->numReasons][0] = '';

            printf( "Enter a reason to add to list %s: ", list->listName );
            if ( fgets( list->reasons[list->numReasons], STR_LEN, stdin ) != NULL )
            {
                list->reasons[list->numReasons][ strcspn( list->reasons[list->numReasons], "n" ) ] = '';
            }
            
            ++list->numReasons;
        }
    }

    return success;
}

Another reason of the problem can be related to the data member listName that you should either assign with a string literal or again you need to allocate dynamically a character array that will be pointed to by the data member.

By the way the function printList should be declared like

void printList( const reasonList *list );

instead of

void printList( const reasonList *list );

because it is inefficient to create a copy of an object of the type struct reasonList instead of passing a pointer to it.

Here is a demonstrative program.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LIST_LENGTH 10
#define STR_LEN 50

typedef struct reasonList
{
    char* listName;
    char* reasons[MAX_LIST_LENGTH];
    int numReasons;
} reasonList;

int addReason( reasonList *list )
{
    int success = list->numReasons < MAX_LIST_LENGTH;
 
    if ( success )
    {
        list->reasons[list->numReasons] = malloc( STR_LEN );
        success = list->reasons[list->numReasons] != NULL;

        if ( success )
        {
            list->reasons[list->numReasons][0] = '';

            printf( "Enter a reason to add to list %s: ", list->listName );
            if ( fgets( list->reasons[list->numReasons], STR_LEN, stdin ) != NULL )
            {
                list->reasons[list->numReasons][ strcspn( list->reasons[list->numReasons], "n" ) ] = '';
            }
            
            ++list->numReasons;
        }
    }

    return success;
}

void printList( const reasonList *list )
{
    printf( "List %sn", list->listName);
    printf("---------n");
    for ( int i = 0; i < list->numReasons; i++ )
    {
        printf( "%sn", list->reasons[i] );
    }
}

int main(void) 
{
    reasonList list = { .listName = "List of reasons", .numReasons = 0 };
    
    addReason( &list );
    
    printList( &list );
    
    return 0;
}

The program output might look like

Enter a reason to add to list List of reasons: Unallocated memory
List List of reasons
---------
Unallocated memory

If you will allocate memory for reasons dynamically then you should free all allocated memory before exiting the program.

Понравилась статья? Поделить с друзьями:
  • Error reading boot sector victoria
  • Error reading bios date from registry
  • Error read only file system ubuntu
  • Error read only file system during write on dev disks
  • Error read econnreset node js