confusing pointer error while implementing linked list - pointers

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MALLOC(p,s) {\
if (!((p) = malloc(s))) { \
fprintf(stderr, "insufficient memory");\
exit(EXIT_FAILURE);\
}\
}
#define IS_EMPTY(first) (!first)
typedef struct listNode* listPointer;
typedef struct listNode {
int data;
listPointer link;
}listNode;
void printList(listPointer first);
int main(void)
{
int x;
int tmpData;
listPointer first = NULL;
listPointer tmpLink = NULL;
FILE* fp = NULL;
if (!(fp = fopen("in.txt", "r"))) {
fprintf(stderr, "cannot open the file");
exit(EXIT_FAILURE);
}
while (!feof(fp)) {
fscanf(fp, "%d", &tmpData);
MALLOC(tmpLink, sizeof(listNode));
if (IS_EMPTY(first)) {
MALLOC(first, sizeof(listNode));
*tmpLink = *first;
}
tmpLink->data = tmpData;
tmpLink = tmpLink->link;
}
printList(first);
}
void printList(listPointer first)
{
for (; first; first = first->link) {
printf("%d ", first->data);
}
printf("\n");
}
We know that we can implement the insert function.
But I'm really curious about why this doesn't work.
What "first" refers to and what "tmpLink" refers to is the same
After implementing the link list while updating tmpLink,
I'm going to use "first" to print later.
I've spent almost a day just thinking about this, and I've tried debugging it, but I don't know why.

Related

Segmentation fault inside range

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue> // std::priority_queue
using std::vector;
using std::cin;
using std::cout;
struct fj{
int indexI=0;
int freeT=0;
};
struct DereferenceCompareNode : public std::binary_function<fj, fj, bool>
{
bool operator()(const fj lhs, const fj rhs) const
{
return lhs.freeT > rhs.freeT;
}
};
class JobQueue {
private:
int num_workers_;
vector<int> jobs_;
vector<int> assigned_workers_;
vector<long long> start_times_;
void WriteResponse() const {
for (int i = 0; i < jobs_.size(); ++i) {
cout << assigned_workers_[i] << " " << start_times_[i] << "\n";
}
}
void ReadData() {
int m;
cin >> num_workers_ >> m;
jobs_.resize(m);
std::cout<<"Read fault"<<"\n";
for(int i = 0; i < m; i++)
cin >> jobs_[i];
std::cout<<"Read fault ends"<<"\n";
}
void AssignJobs() {
// TODO: replace this code with a faster algorithm.
std::cout<<"Fault point 1"<<"\n";
assigned_workers_.resize(jobs_.size());
start_times_.resize(jobs_.size());
vector<long long> next_free_time(num_workers_, 0);
std::priority_queue<int, vector<int>, std::greater<int> > thread;
std::priority_queue<fj, vector<fj>, DereferenceCompareNode > freeJob;
/*
for (int i = 0; i < jobs_.size(); ++i) {
int duration = jobs_[i];
int next_worker = 0;
for (int j = 0; j < num_workers_; ++j) {
if (next_free_time[j] < next_free_time[next_worker])
next_worker = j;
}
assigned_workers_[i] = next_worker;
start_times_[i] = next_free_time[next_worker];
next_free_time[next_worker] += duration;
}
*/
std::cout<<"dump point 2"<<"\n";
for(int i=0;i<num_workers_;i++){
thread.push(i);
}
std::cout<<"dump point 1"<<"\n";
int counter = 0;
while(jobs_.size()!=0){
std::cout<<"jobs_.size:"<<jobs_.size()<<"\n";
std::cout<<"freeJob.size:"<<freeJob.size()<<"\n";
//check logic
do{
if(freeJob.top().freeT == counter){
std::cout<<"freeJob.top().freeT:"<<freeJob.top().freeT<<"\n";
std::cout<<"counter:"<<counter<<"\n";
thread.push(freeJob.top().indexI);
freeJob.pop();
}else{
break;
}
}
while(freeJob.size()!=0);
std::cout<<"Thread:"<<thread.size()<<"\n";
while(thread.size()!=0){
if(jobs_.size()!=0){
fj currA;
currA.indexI = thread.top();
currA.freeT = jobs_.at(0)+counter;
std::cout<<"currA.indexI:"<<currA.indexI<<"\n";
std::cout<<"currA.freeT:"<<currA.freeT<<"\n";
thread.pop();
jobs_.erase(jobs_.begin());
assigned_workers_.push_back(currA.indexI);
start_times_.push_back(currA.freeT);
}else{
break;
}
}
counter++;
}
}
public:
void Solve() {
ReadData();
AssignJobs();
WriteResponse();
}
};
int main() {
std::ios_base::sync_with_stdio(false);
JobQueue job_queue;
job_queue.Solve();
return 0;
}
I am getting segmentation fault in function ReadData while taking inputs for vector jobs.
I am getting fault even when I am inside bounds of defined size.
Everything was fine when have not written AssignJob function.
Am I doing something wrong with some bounds or taking illegal inputs format or messing with some other stuff?
Am I doing something wrong
Yes, you are: freeJob starts out empty, so this is undefined behavior:
if(freeJob.top().freeT == counter){
In fact, you never push anything into freeJob, you only pop() things from it.

QAudioOutput buffer underflow

Getting a message "Got a buffer underflow!" after each write in this simple program.
Beep.hpp:
#pragma once
#include <QTimer>
#include <QAudioOutput>
class Beep: public QObject
{
Q_OBJECT
public:
explicit Beep();
virtual ~Beep();
void onTimer();
private:
QAudioOutput m_out;
QIODevice *m_outDev;
QTimer m_timer;
};
Beep.cpp:
#include "Beep.hpp"
int ms = 100;
const QAudioFormat defaultAudioFormat = []()
{
QAudioFormat format;
format.setSampleRate(8000);
format.setChannelCount(1);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
return format;
}();
Beep::Beep() :
m_out(defaultAudioFormat),
m_outDev()
{
m_out.setBufferSize(16 * ms);
m_outDev = m_out.start();
QObject::connect(&m_timer, &QTimer::timeout, this, &Beep::onTimer);
m_timer.setSingleShot(false);
m_timer.start(ms);
}
Beep::~Beep()
{
}
void Beep::onTimer()
{
std::vector<uint8_t> samples(16 * ms);
m_outDev->write((char*) &samples.front(), samples.size());
}
main.cpp:
#include <QCoreApplication>
#include "Beep.hpp"
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
Beep beep;
return app.exec();
}
This test program is just writing buffers with zeros. With real data there are cracking sounds.
Writing more data or changing timings makes it worse. What's wrong with this code?
Using a Timer is the wrong way to do it.
Use the notify() signal
void AudioManager::init_audio(AudioManager *mgr) {
if (mgr->stream_id == -1) return;
mgr->audio_format.setSampleRate(mgr->context->time_base.den);
mgr->audio_format.setSampleSize(16);
mgr->audio_format.setChannelCount(2);
mgr->audio_format.setCodec("audio/pcm");
mgr->audio_format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(mgr->audio_format)) {
mgr->audio_format = info.nearestFormat(mgr->audio_format);
}
mgr->audio_out = new QAudioOutput(mgr->audio_format, nullptr);
mgr->audio_out->setNotifyInterval(15);
mgr->audio_out->setBufferSize(mgr->context->time_base.den * 4); // 1 second worth of stereo data
connect(mgr->audio_out, SIGNAL(notify()), mgr, SLOT(audio_out_notify()));
connect(mgr->audio_out, SIGNAL(stateChanged(QAudio::State)), mgr, SLOT(audio_out_state_changed(QAudio::State)));
qreal volume_out = (qreal)parent->volume / 100.0f;
mgr->audio_out->setVolume(volume_out);
mgr->audio_out_device = mgr->audio_out->start();
}
This will be called when the audio playback requires more data
void AudioManager::audio_out_notify() {
qDebug() << "Audio notify";
check_audio_playback();
}
Most of the below code will be irrelevant but it is also called is audio has stopped playing.
void AudioManager::check_audio_playback() {
if (stream_id == -1) return;
pthread_mutex_lock(&audio_mutex);
if (!audio_out->state() == QAudio::State::IdleState) {
pthread_mutex_unlock(&audio_mutex);
return;
}
if (parent->pts_start_time < 0.0) {
if (parent->Video.stream_id == -1 && decode_pos > 65) { // start playback
parent->pts_start_time = buffers[0].frame_time;
parent->sys_start_time = (double)parent->timer.elapsed() / 1000.0;
qDebug() << "Audio playback started";
} else {
pthread_mutex_unlock(&audio_mutex);
return;
}
}
if (playback_pos == decode_pos) {
pthread_mutex_unlock(&audio_mutex);
return;
}
AudioBuffer *buffer = nullptr;
double current_sys_time = ((double)parent->timer.elapsed() / 1000.0) - parent->sys_start_time;
bool bounds = false;
int skipped = 0;
while (!bounds) {
if (playback_pos == decode_pos) bounds = true;
else {
AudioBuffer *temp_buffer = &buffers[playback_pos];
double temp_time = temp_buffer->frame_time - parent->pts_start_time;
if (temp_time < current_sys_time ) {
if (buffer) {
buffer->used = false;
skipped++;
}
buffer = temp_buffer;
playback_pos++; playback_pos %= MAX_AUD_BUFFERS;
} else {
bounds = true;
}
}
}
if (skipped > 0) qDebug("Skipped %d audio buffers on playback", skipped);
if (buffer) {
audio_out_device->write((const char *)buffer->data, buffer->buffer_size);
buffer->used = false;
}
pthread_mutex_unlock(&audio_mutex);
}
The example on the Qt website wasn't that obvious http://qt.apidoc.info/5.1.1/qtmultimedia/audiooutput.html at first but when I put it in to test it wasn't too bad.
The reason was that the source of audio data wasn't a "production-quality module" (it's a dummy testing class): the timer was drifting because its real interval was 10ms plus the processing time.
Other observations:
make QAudioOutput::setBufferSize() bigger
do QAudioInput::read() and QAudioOutput::write() in chunks with size that matches QAudioInput::periodSize() and QAudioOutput::periodSize()

How to attach to existing shared memory from Qt?

I have created a shared memory segment with the help of a binary in C and written some data into it. Now I want read that data from Qt. How to attach to existing shared memory from Qt?
QSharedMemory isn't really meant to interoperate with anything else. On Unix, it is implemented via SYSV shared memory, but it passes Qt-specific arguments to ftok:
::ftok(filename.constData(), qHash(filename, proj_id));
You could emulate this behavior in your C code, but I don't think it's necessary.
Instead of opening a shared memory segment, simply map a file to memory, and access it from multiple processes. On Qt, QFile::map does what you need.
The example below shows both techniques: using SYSV shared memory and using memory-mapped files:
// https://github.com/KubaO/stackoverflown/tree/master/questions/sharedmem-interop-39573295
#include <QtCore>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <stdexcept>
#include <string>
First, let's have a shared data structure.
struct Data {
int a = 1;
bool b = true;
char c = 'S';
bool operator==(const Data & o) const { return o.a == a && o.b == b && o.c == c; }
static void compare(const void * a, const void * b) {
auto data1 = reinterpret_cast<const Data*>(a);
auto data2 = reinterpret_cast<const Data*>(b);
Q_ASSERT(*data1 == *data2);
}
};
We definitely want error checking, so let's add some helpers that make that easier:
void check(bool ok, const char * msg, const char * detail) {
if (ok) return;
std::string str{msg};
str.append(": ");
str.append(detail);
throw std::runtime_error{str};
}
void check(int f, const char * msg) { check(f != -1, msg, strerror(errno)); }
void check(void * f, const char * msg) { check(f != MAP_FAILED, msg, strerror(errno)); }
void check(bool rc, const QSharedMemory & shm, const char * msg) { check(rc, msg, shm.errorString().toLocal8Bit()); }
void check(bool rc, const QFile & file, const char * msg) { check(rc, msg, file.errorString().toLocal8Bit()); }
And we need RAII wrappers for C APIs:
struct noncopyable { Q_DISABLE_COPY(noncopyable) noncopyable() {} };
struct ShmId : noncopyable {
int id;
ShmId(int id) : id{id} {}
~ShmId() { if (id != -1) shmctl(id, IPC_RMID, NULL); }
};
struct ShmPtr : noncopyable {
void * ptr;
ShmPtr(void * ptr) : ptr{ptr} {}
~ShmPtr() { if (ptr != (void*)-1) shmdt(ptr); }
};
struct Handle : noncopyable {
int fd;
Handle(int fd) : fd{fd} {}
~Handle() { if (fd != -1) close(fd); }
};
Here's how to interoperates SYSV shared memory sections between C and Qt. Unfortunately, unless you reimplement qHash in C, it's not possible:
void ipc_shm_test() {
QTemporaryFile shmFile;
check(shmFile.open(), shmFile, "shmFile.open");
// SYSV SHM
auto nativeKey = QFile::encodeName(shmFile.fileName());
auto key = ftok(nativeKey.constData(), qHash(nativeKey, 'Q'));
check(key, "ftok");
ShmId id{shmget(key, sizeof(Data), IPC_CREAT | 0600)};
check(id.id, "shmget");
ShmPtr ptr1{shmat(id.id, NULL, 0)};
check(ptr1.ptr, "shmat");
new (ptr1.ptr) Data;
// Qt
QSharedMemory shm;
shm.setNativeKey(shmFile.fileName());
check(shm.attach(QSharedMemory::ReadOnly), shm, "shm.attach");
auto ptr2 = shm.constData();
Data::compare(ptr1.ptr, ptr2);
}
Here's how to interoperate memory-mapped files:
void mmap_test() {
QTemporaryFile shmFile;
check(shmFile.open(), "shmFile.open");
shmFile.write({sizeof(Data), 0});
check(true, shmFile, "shmFile.write");
check(shmFile.flush(), shmFile, "shmFile.flush");
// SYSV MMAP
Handle fd{open(QFile::encodeName(shmFile.fileName()), O_RDWR)};
check(fd.fd, "open");
auto ptr1 = mmap(NULL, sizeof(Data), PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd.fd, 0);
check(ptr1, "mmap");
new (ptr1) Data;
// Qt
auto ptr2 = shmFile.map(0, sizeof(Data));
Data::compare(ptr1, ptr2);
}
And finally, the test harness:
int main() {
try {
ipc_shm_test();
mmap_test();
}
catch (const std::runtime_error & e) {
qWarning() << e.what();
return 1;
}
return 0;
}

reason for runtime error in my c program &?

#include<stdio.h>
main()
{char *names[4];
int i,a;
printf("ënter the guests names\n");
for(i=0;i<=3;i++)
{
scanf("%s",names[i]);
}
char *yourname;
printf("\nenter your name ");
scanf("%c",yourname);
for(i=0;i<=3;i++)
{a=strcmp(names[i],yourname);
if(a==0)
printf("\nwelcome");
break;
}
if(a!=0)
printf("\naccess denied");
return 0;
}
this is a program to check your entry in a show. first we give permitted names & then it asks your name ,it compares your name with the names in the guest list.
i m getting runtime error, plz tell me the correction.i want to use pointers to string so plz suggest correction in the existing program
when i run this program in devc++ after entering first name it gives program.exe stopped working.
The code will be like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *names[4];
int i,a;
printf("ënter the guests names\n");
for(i=0;i<=3;i++) {
names[i] = (char*) malloc(100 * sizeof(char));
scanf("%s", names[i]);
}
char yourname[100];
printf("\nenter your name ");
scanf("%s",yourname);
for(i=0;i<=3;i++) {
a = strcmp(names[i], yourname);
if (a == 0) break;
}
if (a==0)
printf("\nwelcome");
else printf("\naccess denied");
for(i=0;i<=3;i++)
free(names[i]);
return 0;
}
Your code have to be formated so we can give you a better answer.
Now, use gets to take your input, verify the guest match with your name inside the for loop, stop the loop when a match is found.
#include<stdio.h>
#include<string.h>
int main()
{
char names[4][20];
int i = 0;
int a = 0;
printf("Enter guests names: \n");
for(i=0; i<3; i++)
{
gets(names[i]);
}
char yourname[20];
printf("\n Enter your name ");
gets(yourname);
printf("\n Verify access right:");
for(i=0; i<3; i++)
{
a=strcmp(names[i], yourname);
if(a==0)
{
printf("\n welcome");
break;
}
else
{
printf("\n access denied");
}
}
return 0;
}
Although this looks like a homework assignment.

Error writing and reading a structure from PIPE

I have a client server program where client writes a command on PIPE for server. While reading the command from Server it reads only first char of command and throws error. Can anyone help me with this?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/wait.h>
#include <mqueue.h>
#include <sys/stat.h>
#include "Functions.h"
#define MSGBUFFER_SIZE 50000
pid_t serverPid;
pid_t clientPid;
typedef struct msgbuf {
int messageLength;
int messageType;
char messageText[MSGBUFFER_SIZE];
} Message_buf;
int writePIPE(int fd, Message_buf *inputMessage){
printf("\n In write pipe message length :%d",inputMessage->messageLength);
printf("\n In write pipe message Data :%s",inputMessage->messageText);
ssize_t n=write(fd,inputMessage,inputMessage->messageLength);
printf("\n Size :%d", n);
return n;
}
ssize_t readPIPE(int fd, Message_buf *outputMessage)
{
ssize_t len;
ssize_t n;
if((n=read(fd,outputMessage,sizeof(outputMessage)))==0)
{
printf("\n Error");
return 0;
}
if((len=outputMessage->messageLength)>0)
{
printf("\n Length ---->:%d",len);
if((n=read(fd,outputMessage->messageText,strlen(outputMessage->messageText)))!=len)
printf("\n ERRRRROR expected %d got %d",len,n);
}
//printf("\n In Read PIPE: %s",outputMessage->messageText);
return len;
}
void Server(int readfd,int writefd)
{
Message_buf server_MessageBuf;
ssize_t length;
if((length=readPIPE(readfd,&server_MessageBuf))==0)
{
printf("\n End of file while reading pathname");
}
//server_MessageBuf.messageText[length]='\0';
printf("\n LENGTH :%d",server_MessageBuf.messageLength);
printf("\n Printing in server: %s\n",server_MessageBuf.messageText);
}
void Client(int readfd,int writefd)
{
char inputFileName[MAX_SIZE];
char inputOperation[MAX_SIZE];
char *cCommandInput = NULL;
char *fileOperation = NULL;
char *operation = (char *) malloc(MAX_SIZE);
int commandValidateStatus = 0;
int commandInterpretationStatus=0;
Message_buf client_MessageBuf;
for(;;)
{
while(1)
{
cCommandInput = acceptInput();
fileOperation = (char *) malloc(sizeof(cCommandInput));
strcpy(fileOperation,cCommandInput);
/**Function call to determine operation read/delete/exit/invalid choice and filename*****/
commandInterpretationStatus = interpretCommand(cCommandInput,
inputOperation, inputFileName);
operation = inputOperation;
/**Function call to validate the input command******/
commandValidateStatus = validateCommand(
commandInterpretationStatus, inputOperation, inputFileName);
if(commandValidateStatus==-1)
{
printf("\n Invalid Operation");
}
/*Exit command entered***/
if (commandValidateStatus == 1)
{
/*Code to clear resources */
kill(serverPid,SIGKILL);
kill(clientPid,SIGKILL);
exit(0);
}
/***Read or Delete****/
if (commandValidateStatus == 2 || commandValidateStatus == 3)
{
printf("\n Read or Delete\n");
strcpy(client_MessageBuf.messageText,fileOperation);
client_MessageBuf.messageLength=strlen(fileOperation);
client_MessageBuf.messageType=1;
if((writePIPE(writefd,&client_MessageBuf))<0)
{
printf("\n Error writing on client side ");
}
//read(readfd,*client_MessageBuf,sizeof(client_MessageBuf));
//printf("\n Reding server responsed");
//printf("%s",client_MessageBuf.messageText);
}
}
}
}
int main()
{
int pipe1[2],pipe2[2];
pipe(pipe1);
pipe(pipe2);
pid_t pid;
pid=fork();
serverPid=pid;
if(pid==0)
{
/*Call Server*/
close(pipe1[1]);
close(pipe2[0]);
Server(pipe1[0], pipe2[1]);
}
else
{
close(pipe1[0]);
close(pipe2[1]);
Client(pipe2[0],pipe1[1]);
}
return 0;
}
It looks like the code writes and reads struct msgbuf incorrectly:
typedef struct msgbuf {
int messageLength;
int messageType;
char messageText[MSGBUFFER_SIZE];
} Message_buf;
// ...
strcpy(client_MessageBuf.messageText,fileOperation);
client_MessageBuf.messageLength=strlen(fileOperation);
client_MessageBuf.messageType=1;
if((writePIPE(writefd,&client_MessageBuf))<0)
// ....
int writePIPE(int fd, Message_buf *inputMessage){
printf("\n In write pipe message length :%d",inputMessage->messageLength);
printf("\n In write pipe message Data :%s",inputMessage->messageText);
ssize_t n=write(fd,inputMessage,inputMessage->messageLength);
printf("\n Size :%d", n);
return n;
}
The above pieces that write struct msgbuf only write the first messageLength bytes of the structure which doesn't include the length of messageLength and messageType members, i.e. it truncates the object.
When reading:
ssize_t readPIPE(int fd, Message_buf *outputMessage)
{
// ...
if((n=read(fd,outputMessage,sizeof(outputMessage)))==0)
It reads only sizeof(outputMessage) bytes, which is the size of the pointer, not the object. Even if you fix it by changing it to sizeof(*outputMessage) that won't do enough, since that would expect to read the complete object whereas the writing piece truncates the object.
A good start to fix it would be to split the message into two parts: header and payload. The header is a structure of a fixed size, e.g.:
typedef struct {
int messageType;
int payloadLength;
} MessageHeader;
The payload is a variable-length part following the header. This way it would first write the entire header object into the pipe followed by payloadLength bytes of payload. When reading it would first read again the entire header and then read exactly payloadLength bytes.
Also note, that read() and write() calls may read or write less then asked, so that case needs to be explicitly handled by keeping reading or writing until the exact number of bytes has been processed.

Resources