Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.53/15: Рейтинг темы: голосов - 15, средняя оценка - 4.53
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90

Непонятные символы при возврате строки из функции

19.02.2018, 20:47. Показов 3154. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет!

Работаю с "NVAPI" (Библиотека, которая позволяет работать с видеокартами NVIDIA). В ней есть тип переменной "NvAPI_ShortString" (за место обычного "string").

Приведу кусок кода, а дальше объясню:

C++
1
2
3
4
NvAPI_ShortString name; //Задаем переменную, в которой будет хранится название видеокарты.
NvAPI_GPU_GetFullName(phys[0], name); //Получаем название 1-ой видеокарты и записываем название в переменную name.
 
cout << name << endl;
Теперь, если вывести переменную name, с помощью "cout", то я увижу корректное название видеокарты (хотя name определена как "NvAPI_ShortString", а не "string" или "const char*").

Идем дальше: добавляем перевод name из "NvAPI_ShortString" в "const char*":

C++
1
2
3
4
5
6
7
8
NvAPI_ShortString name; //Задаем переменную, в которой будет хранится название видеокарты.
NvAPI_GPU_GetFullName(phys[0], name); //Получаем название 1-ой видеокарты и записываем название в переменную name.
 
stringstream dd(name);
string tmp = dd.str();
const char* f = tmp.c_str();
 
cout << f << endl;
При выводе так же получаем корректное название видеокарты.

Теперь подходим к проблеме: если создать функцию, которая возвращает "const char*" (то есть f из предыдущего кода), а потом попробовать вывести f, то на экране будут полоски, разные символы, вместо названия видеокарты.

Вот код:

C++
1
2
3
4
5
6
7
8
9
10
11
const char* NVAPI_namePhysicalGPUs()
{
 NvAPI_ShortString name; //Задаем переменную, в которой будет хранится название видеокарты.
 NvAPI_GPU_GetFullName(phys[0], name); //Получаем название 1-ой видеокарты и записываем название в переменную name.
 const char* f;
 
 stringstream dd(name);
 string tmp = dd.str();
 f = tmp.c_str();
 return f;
}
Почему функция возвращает кракозябры, а без функции все хорошо работает?

Заранее спасибо!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.02.2018, 20:47
Ответы с готовыми решениями:

Проблема при возврате строки из функции
Привет всем. Извините за ночное беспокойствие. #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;ctype.h&gt; #include...

Непонятные символы.(Строки и указатели).
Добрый вечер. Задание - Написать программу получения строки, в которой удалены все “лишние” пробелы, т.е. из нескольких подряд идущих...

Строки (добавляет какие-то непонятные символы)
Есть функция, которая возвращает строку. char *create_string(int Q1, int Q2, int Q3, int S1, int S2, int S3, float T) { int Q; int...

14
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
19.02.2018, 21:30
Потому что f -это указатель. Память под строку выделена в tmp, а f просто указывает на эту память. При выходе из функции объект tmp уничтожится, удалится и память со строкой. f продолжит указывать на память, которая уже освобождена и может использоваться программой для иных целей. Почему бы просто не сделать так?
C++
1
2
3
4
5
6
const char* NVAPI_namePhysicalGPUs()
{
 NvAPI_ShortString name; //Задаем переменную, в которой будет хранится название видеокарты.
 NvAPI_GPU_GetFullName(phys[0], name); //Получаем название 1-ой видеокарты и записываем название в переменную name.
 return name;
}
Добавлено через 27 минут
Не, так не пойдёт.
Code
1
typedef char    NvAPI_ShortString[NVAPI_SHORT_STRING_MAX]
Сделайте лучше возврат из функции объекта string, вместо указателя.
0
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
19.02.2018, 22:14  [ТС]
Проблема в том, что я пишу DLL и мне надо вернуть именно "char*".

Все-таки попробовал вариант со "string", но все равно выводит кракозябры (ну уже другие).

Есть еще какой-нибудь вариант?

Добавлено через 8 минут
Еще возник вопрос: почему при задание этих переменных глобально, ничего не меняется? Ведь в таком случае ничего не удаляется при выходе из функции.
0
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
19.02.2018, 22:37
Цитата Сообщение от zzzzza Посмотреть сообщение
Есть еще какой-нибудь вариант?
Полно, можно в вашу функцию передать массив char и в нём вернуть значение, можно выделить память динамически, скопировать туда строку и вернуть указатель на неё и т.д.

Еще возник вопрос: почему при задание этих переменных глобально, ничего не меняется? Ведь в таком случае ничего не удаляется при выходе из функции.
Сложно что-либо сказать не видя кода, может вы указатель глобально объявляете, а это ничего не меняет.
0
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
19.02.2018, 22:44  [ТС]
А можете, пожалуйста, привести код для второго варианта: выделить память динамически, скопировать туда строку и вернуть указатель?

Да, так я и делал(
0
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
19.02.2018, 22:55
C++
1
2
3
4
5
6
7
8
9
10
11
12
const char* NVAPI_namePhysicalGPUs()
{
  NvAPI_ShortString name; //Задаем переменную, в которой будет хранится название видеокарты.
  NvAPI_GPU_GetFullName(phys[0], name); //Получаем название 1-ой видеокарты и записываем название в переменную name.
 
  size_t len = strlen(name);
  char* pBuffer = (char*)malloc(len + 1);// можно new
  if (pBuffer)
    strcpy(pBuffer, name);
 
  return pBuffer;
}
Такой вариант плох тем, что вызывающая сторона должна будет потом освободить память, что бы не было утечек. Нужно будет вызвать free (delete, если был new). Если DLL и EXE будут скомпилированы с разными настройками (например, одно debug, другое release), то произойдёт исключение и всё развалится.
1
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
19.02.2018, 23:09  [ТС]
Не поверите, но опять иероглифы(

Если нужно, то могу весь код скинуть, но думаю, что в этом мало толка.
0
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
19.02.2018, 23:28
Можно зайти с другой стороны, откуда берётся параметр phys[0]?
Возможно, что в работающих исходниках он был получен корректно, а в неработающих он ошибочен.
Если программа не очень большая, то выкладывайте.
0
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
19.02.2018, 23:40  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
 
using namespace std;
 
#pragma comment(lib, "nvapi.lib")
#include "nvapi.h"
 
NvPhysicalGpuHandle phys[NVAPI_MAX_PHYSICAL_GPUS];
NvU32 cnt;
 
const char* NVAPI_namePhysicalGPUs()
{
    NvAPI_ShortString name;
    NvAPI_GPU_GetFullName(phys[0], name); //phys задана глобально.
 
    size_t len = strlen(name);
    char* pBuffer = (char*)malloc(len + 1);// можно new
    if (pBuffer)
        strcpy(pBuffer, name);
 
    return pBuffer;
}
 
int main()
{
    NvAPI_Initialize(); //Инициализируем NVAPI.
        NvAPI_EnumPhysicalGPUs(phys, &cnt); //Заполняем массив phys физическими видеокартами (точнее их хэндлами). 
        //В cnt хранится кол-во видеокарт.
 
    cout << NVAPI_namePhysicalGPUs() << endl;
    
    getchar();
    return 0;
}
0
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
20.02.2018, 00:09
Странно, потому что у меня ваш код работает, печатается строка "GeForce 210"
0
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
20.02.2018, 00:19  [ТС]
Хмм, очень странно. Именно этот код у меня тоже правильно все выводит.

Хотел оставить основную часть кода, но придется скинуть весь код полностью:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
 
using namespace std;
 
#pragma comment(lib, "nvapi.lib")
#include "nvapi.h"
 
 
const char* NVAPI_namePhysicalGPUs(NvPhysicalGpuHandle* phys, double number)
{
    NvAPI_Status ret;
    NvAPI_ShortString name;
    const char* f;
 
    int n = number;
 
    if ((number > 0) && (number <= 1))
    { //Существует такой индекс видеокарты.
        ret = NvAPI_GPU_GetFullName(phys[n], name);
        if (ret != NVAPI_OK)
        {
            size_t len = strlen(name);
            char* pBuffer = (char*)malloc(len + 1);// можно new
            if (pBuffer)
                strcpy(pBuffer, name);
 
            return pBuffer;
        }
        else
        {
            f = "W";
            return f;
        }
    }
    else
    {
        f = "Y";
        return f;
    }
}
 
 
 
 
int main()
{
    NvAPI_Status ret = NVAPI_OK;
    int i = 0;
 
    NvDisplayHandle hDisplay_a[NVAPI_MAX_PHYSICAL_GPUS * 2] = { 0 };
 
    ret = NvAPI_Initialize();
 
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NVAPI NvAPI_Initialize: " << string << endl;
    }
 
    NvAPI_ShortString ver;
 
    NvAPI_GetInterfaceVersionString(ver);
    cout << "NVAPI Version: " << ver << endl;
 
    NvU32 cnt;
 
    NvPhysicalGpuHandle phys[NVAPI_MAX_PHYSICAL_GPUS];
 
    ret = NvAPI_EnumPhysicalGPUs(phys, &cnt);
 
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NVAPI NvAPI_EnumPhysicalGPUs: " << string << endl;
    }
    
    NvAPI_ShortString name;
 
    NV_GPU_THERMAL_SETTINGS thermal;
    cout << NVAPI_namePhysicalGPUs(phys, 1) << endl; //ИЕРОГЛИФЫ ВЫВОДЯТСЯ В ЭТОЙ СТРОКЕ!
    ret = NvAPI_GPU_GetFullName(phys[0], name);
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NVAPI NvAPI_GPU_GetFullName: " << string << endl;
    }
 
    stringstream dd(name);
    string tmp = dd.str();
    const char* f = tmp.c_str();
    cout << "Name: " << f << endl;
    thermal.version = NV_GPU_THERMAL_SETTINGS_VER;
    ret = NvAPI_GPU_GetThermalSettings(phys[0], 0, &thermal);
 
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NVAPI NvAPI_GPU_GetThermalSettings: " << string << endl;
    }
    cout << "Temp: " << thermal.sensor[0].currentTemp << endl;
 
    //Скорость вращения кулера.
    NvU32 nSpeed;
    ret = NvAPI_GPU_GetTachReading(phys[0], &nSpeed);
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NVAPI NvAPI_GPU_GetTachReading: " << string << endl;
    }
    cout << "Cooler speed: " << nSpeed << endl;
 
    //Pstate.
    NV_GPU_PERF_PSTATE_ID pCurrentPstate;
    ret = NvAPI_GPU_GetCurrentPstate(phys[0], &pCurrentPstate);
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NvAPI_GPU_GetCurrentPstate: " << string << endl;
    }
    cout << "Pstate: " << pCurrentPstate << endl;
 
    //Производительность.
    NV_GPU_DYNAMIC_PSTATES_INFO_EX pDynamicPstatesInfoEx;
    ret = NvAPI_GPU_GetDynamicPstatesInfoEx(phys[0], &pDynamicPstatesInfoEx);
    if (!ret == NVAPI_OK) {
        NvAPI_ShortString string;
        NvAPI_GetErrorMessage(ret, string);
        cout << "NvAPI_GPU_GetDynamicPstatesInfoEx: " << string << endl;
    }
    cout << "Load: " << pDynamicPstatesInfoEx.utilization << endl;
    
    
    getchar();
    return 0;
}
Добавлено через 35 секунд
Вот он точно иероглифы выводит.
0
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
20.02.2018, 00:34
1) Индексы массивов начинаются с 0, правильно было бы написать (у меня одна карта, только с 0)
C++
1
2
//cout << NVAPI_namePhysicalGPUs(phys, 1) << endl; //ИЕРОГЛИФЫ ВЫВОДЯТСЯ В ЭТОЙ СТРОКЕ!
cout << NVAPI_namePhysicalGPUs(phys, 0) << endl; //ИЕРОГЛИФЫ ВЫВОДЯТСЯ В ЭТОЙ СТРОКЕ!
2) Передавать индекс как число с плавающей точкой особого смысла нет.
C++
1
2
//const char* NVAPI_namePhysicalGPUs(NvPhysicalGpuHandle* phys, double number)
const char* NVAPI_namePhysicalGPUs(NvPhysicalGpuHandle* phys, int number)
3) Проверка успешности при получении имени выполняется некорректно
C++
1
2
3
ret = NvAPI_GPU_GetFullName(phys[number], name);
//if (ret != NVAPI_OK)
if (ret == NVAPI_OK)
1
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
20.02.2018, 00:43  [ТС]
Такие глупые ошибки и столько времени из-за этого потрачено

Огромное спасибо за помощь, без Вас я бы так и не заметил, что индекс с нуля начинается. Извиняюсь, что отнял у Вас время.
1
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,120
20.02.2018, 00:58
Что бы не использовать динамическую память и DLL я бы сделал так.
1) Определил бы структуру со всеми возможными параметрами, включая хендлы и имена по 64 символа (именно столько в NvAPI_ShortString)
2) Сделал бы глобальный массив этих структур, штуки 4 наверное хватит.
3) В функции инициализации DLL заполнил бы поля этих структур.
4) При запросе имени просто бы возвращал указатель на уже считанное имя из этого массива.
1
7 / 7 / 2
Регистрация: 24.02.2013
Сообщений: 90
20.02.2018, 01:08  [ТС]
Этим уже займусь завтра, спасибо за совет!)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
20.02.2018, 01:08
Помогаю со студенческими работами здесь

Непонятные символы в начале строки в ответе от сервера
Есть скрипт который выдает json-строку, но в самом начале ее есть невидимые в браузере символы, с хламом от utf-8 или чего другого: п», или...

Затираются значения при возврате из функции initializer_list
Дарова. Объясните, почему при возврате объекта инитиализер_лист из функции значения этого листа трутся #include &lt;iostream&gt; ...

Непонятные символы при гаммировании
реализовал алгоритм гаммирования (симметричного шифрования). Шифрование происходит след путем: байт символа открытого текста в кодировке...

Непонятные символы при выводе
Я уже такую фигню много раз наблюдал типа если не поставить '\0' или убрать при выводе какие то непонятные символы идут от пример. ...

Особенности использования указателей и ссылок в C++ при возврате из функции
Пусть у нас есть некий класс CBase и есть функция, которая создает и возвращает объект класса CBase. Создать она его может стеке или в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru