Iterate C array struct in Go - c

package main
//#cgo LDFLAGS: -ldl -lp11
//#include <stdlib.h>
//#include <libp11.h>
import "C"
import (
"log"
"unsafe"
"fmt"
//"runtime"
//"reflect"
)
func main(){
var ctx *C.PKCS11_CTX
ctx = C.PKCS11_CTX_new()
//log.Println(ctx)
cModulePath := C.CString("/home/procondutor/libaetpkss.so.3.0.3930")
defer C.free(unsafe.Pointer(cModulePath))
rc := C.PKCS11_CTX_load(ctx, cModulePath)
if rc < 0 {
log.Println("1 erro rc menor que 0")
return
}
var slots, slot *C.PKCS11_SLOT
var keys *C.PKCS11_KEY
var nslots, nkeys uint
p := unsafe.Pointer(&nslots)
n := unsafe.Pointer(&nkeys)
//log.Println(nkeys)
rc = C.PKCS11_enumerate_slots(ctx, &slots, (*C.uint)(p))
if rc < 0 {
log.Println("2 erro rc menor que 0")
return
}
slot = C.PKCS11_find_token(ctx, slots, C.uint(nslots));
s := C.GoString(slot.manufacturer)
fmt.Printf("%+v\n", s)
cPin := C.CString("2903")
defer C.free(unsafe.Pointer(cPin))
rc = C.PKCS11_login(slot, 0, cPin);
if rc < 0 {
log.Println("3 erro rc menor que 0")
return
}
rc = C.PKCS11_enumerate_keys(slot.token, &keys, (*C.uint)(n));
if rc < 0 {
log.Println("4 erro rc menor que 0")
return
}
My problem is in the PKCS11_enumerate_keys function, in C this function returns a list according to the code below:
static void list_keys(const char *title, const PKCS11_KEY *keys,
const unsigned int nkeys) {
unsigned int i;
printf("\n%s:\n", title);
for (i = 0; i < nkeys; i++)
printf(" * %s key: %s\n",
keys[i].isPrivate ? "Private" : "Public", keys[i].label);
}
But in Go it only returns the first object.
If I try to iterate in Go, I get the following error:
invalid operation: cannot index keys (variable of type *_Ctype_struct_PKCS11_key_st)

I finally got it with the code below:
list_keys := unsafe.Slice(keys, nkeys)
for i := 0; i < int(nkeys); i++ {
z:= C.GoString(slice[i].label)
fmt.Println(z)
}

Related

Why OLE DB IRowset.GetNextRows access violation

I'm using OLE DB to retrieve some data from a SQL server, the outline of the code is
m_spCmd->SetCommandText(DBGUID_DEFAULT,L"SELECT * FROM sys.DM_OS_PERFORMANCE_COUNTERS"); // S_OK
CComPtr<IRowset> result;
m_spCmd->Execute(nullptr,__uuidof(IRowset),nullptr,nullptr,(IUnknown**)&result); // S_OK
DBCOUNTITEM fetched;
HROW *hrow;
result->GetNextRows(DB_NULL_HCHAPTER,0,1,&fetched,&hrow); // A
at A , I got an access violation exception (which means something is null, the result itself is not null). I think I have missed some step(s) in the code, what's that? Many thanks!!!
Update
sqlcmd.h
#pragma once
#include <windows.h>
#include <msdaguid.h>
#include <msdasql.h>
#include <oledb.h>
#include <oledberr.h>
#include <iostream>
#include <atlbase.h>
#include <atldbcli.h>
using namespace std;
struct SQLCmd
{
SQLCmd();
~SQLCmd();
private:
template<typename T> void print(T);
private:
CComPtr<IDBInitialize> m_spDb;
CComPtr<IDBProperties> m_spDbProperty;
CComPtr<ISessionProperties> m_spSsProperty;
CComPtr<ICommandText> m_spCmd;
CComPtr<ISQLErrorInfo> m_spErr;
CComPtr<IAccessor> m_spAccessor;
CComPtr<IDBCreateSession> m_spCrsession;
HRESULT hr;
};
sqlcmd.cpp
#include "sqlcmd.h"
template<>
void SQLCmd::print(CComPtr<IRowset> ptr)
{
DBORDINAL count;
DBCOLUMNINFO *info;
OLECHAR *buf;
auto accessor = CComQIPtr<IAccessor>(ptr);
auto colinfo = CComQIPtr<IColumnsInfo>(ptr);
colinfo->GetColumnInfo(&count,&info,&buf);
/*
DBBINDING *bindings = new DBBINDING[count];
memset(bindings,0,sizeof(DBBINDING)*count);
DBBINDSTATUS *bindingstatus = new DBBINDSTATUS[count];
memset(bindingstatus,0,sizeof(DBBINDSTATUS)*count);
DBBYTEOFFSET offset = 0;
int rowsize = 0;
for(int i = 0 ; i < count ; i++)
{
auto &[pwszName,pTypeInfo,iOrdinal,dwFlags,ulColumnSize,wType,bPrecision,bScale,columnid] = info[i];
bindings[i].iOrdinal = iOrdinal;
bindings[i].obValue = offset;
bindings[i].wType = wType;
bindings[i].dwPart = DBPART_VALUE;
bindings[i].bPrecision = bPrecision;
bindings[i].bScale = bScale;
offset += ulColumnSize;
rowsize += ulColumnSize;
printf("%ws %lld %d\n",pwszName,ulColumnSize,wType);
}
HACCESSOR haccessor;
hr = accessor->CreateAccessor(DBACCESSOR_ROWDATA,count,bindings,rowsize,&haccessor,bindingstatus);
printf("CreateAccessor %x %llx\n",hr,haccessor);
for(int i = 0 ; i < count ; i++)
if(DBBINDSTATUS_OK != bindingstatus[i])
printf("%d - %d\n",i,bindingstatus[i]);*/
DBCOUNTITEM fetched;
HROW *hrow;
printf("before GetNextRows\n");
hr = ptr->GetNextRows(DB_NULL_HCHAPTER,0,1,&fetched,&hrow);
printf("GetNextRows %x %lld\n",hr,fetched);
}
SQLCmd::SQLCmd()
{
GUID msoledbsql;
CLSIDFromString(L"{5A23DE84-1D7B-4A16-8DED-B29C09CB648D}",&msoledbsql);
m_spDb.CoCreateInstance(msoledbsql);
m_spDbProperty = CComQIPtr<IDBProperties>(m_spDb);
CDBPropSet set(DBPROPSET_DBINIT);
set.AddProperty(DBPROP_AUTH_INTEGRATED,L"SSPI");
set.AddProperty(DBPROP_INIT_CATALOG,L"master");
set.AddProperty(DBPROP_INIT_DATASOURCE,L"localhost");
m_spDbProperty->SetProperties(1,&set);
m_spDb->Initialize();
auto m_spCrsession = CComQIPtr<IDBCreateSession>(m_spDb);
if (!!m_spCrsession)
{
hr = m_spCrsession->CreateSession(nullptr,__uuidof(ISessionProperties),(IUnknown**)&m_spSsProperty);
auto _ = CComQIPtr<IDBCreateCommand>(m_spSsProperty);
if (!!_)
hr = _->CreateCommand(nullptr,__uuidof(ICommandText),(IUnknown**)&m_spCmd);
}
CComPtr<IRowset> result;
hr = m_spCmd->SetCommandText(DBGUID_DEFAULT,L"SELECT * FROM sys.DM_OS_PERFORMANCE_COUNTERS");
printf("SetCommandText 0x%x\n",hr);
DBROWCOUNT rowcount;
hr = m_spCmd->Execute(nullptr,__uuidof(IRowset),nullptr,&rowcount,(IUnknown**)&result);
printf("Execute 0x%x %lld\n",hr,rowcount);
if (!!result)
{
print(result);
}
}
SQLCmd::~SQLCmd()
{
if (!!m_spDb) m_spDb->Uninitialize();
}
test.cpp
#include "sqlcmd.h"
int main()
{
CoInitialize(nullptr);
SQLCmd cmd;
}
compile
cl /nologo /EHsc /std:c++latest test.cpp sqlcmd.cpp /link /debug
run
>test
SetCommandText 0x0
Execute 0x0 -1
before GetNextRows
IRowset::GetNextRows documentation: says this
If *prghRows is not a null pointer on input, it must be a pointer to
consumer-allocated memory large enough to return the handles of the
requested number of rows. If the consumer-allocated memory is larger
than needed, the provider fills in as many row handles as specified by
pcRowsObtained; the contents of the remaining memory are undefined.
So you can't pass a random pointer on input. You must set it to something valid or NULL:
HROW* hrow = NULL;

Trying to compile a x86 C program on a x64 RedHat environment [Part 2]

Still following the saga of a Cobol developer handling C programs on a environment migration.
I think we could manage 90% of the problems so far and most of our C programs are now compiling fine on the RHEL 64 bits.
Friday we found another module that is not compiling and I hope to be the last one.
I am receiving two warnings, but I have no idea about it and our make does not allow us to compile it properly.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
#include <errno.h>
#include </public/prod/src/mfqinc.h>
static FILE *infile = NULL;
static FILE *outfile = NULL;
char inbuf[1024], blockrec[10240];
static char workstring[1024];
static char workstring0[1024];
static char gra2533h [8];
static char gra2401h [8] ;
static char gra2501h [8] ;
static char gra2506h [8] ;
static char crtn[1] ; /* {"0x0A"};*/
int i;
int z;
int f;
int resulisn;
int j;
int d;
int ctrrec;
int nb_ecrit;
static int longueur;
void initworkstring()
{
extern char workstring [1024];
int ik;
for (ik=0; ik < 1024 ;ik++)
{
workstring [ik] = NULL;
}
}
void ecriture()
{
extern char workstring [1024];
extern int longueur;
extern int ctrrec;
nb_ecrit = fwrite(workstring,sizeof(char),longueur,outfile);
ctrrec++;
if ( nb_ecrit != longueur )
{
printf("andlog:erreur d ecriture ");
printf("Ecrit: %i",nb_ecrit);
printf("Erreur no: %i",errno);
exit(60);
}
}
static void errarg(char *errmsg)
{
fprintf(stderr,"ERROR - %s\nCommand format :\n\t",errmsg);
fprintf(stderr," : \n");
/* exit(1); */
}
main (int argc, char *argv[])
{
if ( argc < 3 )
{
printf("<<< Programme : and015 >>>\n");
printf("<<< Nombre de parametres incorrect >>>\n");
printf("<<< Remove catacteres speciaux >>>\n");
printf("<<< Param # 1 = nom du fichier d'input >>>\n");
printf("<<< Param # 2 = nom du fichier d'output >>>\n");
printf("\n");
exit(10);
}
if ((infile = fopen(argv[1],"rb")) == NULL )
{
printf("Erreur sur fichier input \n");
exit(20);
}
if ((outfile = fopen(argv[2],"wb")) == NULL )
{
printf("Erreur sur fichier output \n");
exit(30);
}
initworkstring();
/* remplir les table de catacteres */
crtn[0]=0x0a;
gra2533h[0]=0x1b;
gra2533h[1]=0x5b;
gra2533h[2]=0x32;
gra2533h[3]=0x35;
gra2533h[4]=0x3b;
gra2533h[5]=0x33;
gra2533h[6]=0x33;
gra2533h[7]=0x48;
gra2401h[0]=0x1b;
gra2401h[1]=0x5b;
gra2401h[2]=0x32;
gra2401h[3]=0x34;
gra2401h[4]=0x3b;
gra2401h[5]=0x30;
gra2401h[6]=0x31;
gra2401h[7]=0x48;
gra2501h[0]=0x1b;
gra2501h[1]=0x5b;
gra2501h[2]=0x32;
gra2501h[3]=0x35;
gra2501h[4]=0x3b;
gra2501h[5]=0x30;
gra2501h[6]=0x31;
gra2501h[7]=0x48;
gra2506h[0]=0x1b;
gra2506h[1]=0x5b;
gra2506h[2]=0x32;
gra2506h[3]=0x35;
gra2506h[4]=0x3b;
gra2506h[5]=0x30;
gra2506h[6]=0x36;
gra2506h[7]=0x48;
while (fgets(inbuf,1024,infile) != NULL )
{
i=0;
j=0;
d=0;
for (i=0; i < 1024 ; i++)
{
if ( inbuf [i] == NULL )
{
i = 9999;
}
else
{
if ( inbuf[i] == 0x1b )
{
i++;
d=0;
for (d=0 ;d < 8; d++)
{
if ( inbuf[i] == 0x48 )
{
j= j-d;
workstring[j]=0x0a;
d=99;
}
else
{
if (inbuf[i] == 0x6d)
{
j= j-d;
workstring[j]=0x0a;
d=99;
}
else
{
if (inbuf[i] == 0x53)
{
j=j-d;
workstring[j]=0x0a;
d=99;
}
else
{
workstring[j] = inbuf[i];
j++;
i++;
}
}
}
} /* end du for*/
}/*fin du if 01b*/
else
{
workstring[j] = inbuf[i];
j++;
}
}
/* mettre dans workstring */
workstring [j] = inbuf [i];
}
strcat(workstring,crtn);
longueur = j ;
ecriture ();
initworkstring();
} /* fin du while */
fclose(infile);
fclose(outfile);
exit(0);
}
Those are the warnings I am having.
/exp/prod/src>gcc -m64 mfqlog.c -o mfqlog
mfqlog.c: In function 'initworkstring':
mfqlog.c:48:20: warning: assignment makes integer from pointer without a cast [enabled by default]
workstring [ik] = NULL;
^
mfqlog.c: In function 'main':
mfqlog.c:146:18: warning: comparison between pointer and integer [enabled by default]
if ( inbuf [i] == NULL )
Really sorry to bother with this question. But I really need to compile this code.
The funny fact is that the program is working (probably, for some unknown reason to me, the program was compiling before and it is not anymore due to changes on the compiler maybe?!?) on our actual environment, but if we try to compile it will fail and the only way to make it working is restoring the executable backup.
As we are moving to a new 64 bits environment, it has to be recompiled.
Thank you all for the help.
NULL is defined as (void*)0. Replace NULL with '\0' or 0.
workstring [ik] = '\0';
if ( inbuf [i] == '\0' )

my C program using pthreads gets stuck and i cant figure it out why

I cant seem to see whre is the problem of my program it do all my computations but at some point get stuck. and i cant figure it out, any recomendations?
first i define the structure
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
int barreira;
int *buffer;
int items_buffer;
int bloqueio_buffer;
int soma_global;
typedef struct {
pthread_mutex_t * mutex;
pthread_cond_t * cond;
pthread_cond_t * produzir;
pthread_cond_t * consumir;
int * matriz;
int numero_thread;
int inicio;
int interacoes;
}estrutura_geral;
void * funcao_calculadora(void *);
void * funcao_somadora(void *);
My main seems doing ok,maybe the problem is that the functions void are notworking correctly
int main(int argc, char ** argv){
int i, n, nt, nbloco, nsomadores;
n=atoi(argv[2]);
nt=atoi(argv[1]);
nbloco=atoi(argv[3]);
nsomadores=1;
barreira=n+1;
if(argc!=4){
printf("Utilização: ./mtss nt n nbloco\n");
exit(1);}
if(nt<1){
printf("O numero de processos terá que ser pelo menos 1\n");
exit(1);}
if(n<1||n>999){
printf("O n tem que estar compreendido entre 1 e 999\n");
exit(1);}
if(nbloco<1){
printf("O bloco tem que ser pelo menos 1\n");
exit(1);
}
if(n<nt){
nt = n;
}
pthread_t * calculadoras = malloc(sizeof(pthread_t)*nt);
pthread_t * somadoras = malloc(sizeof(pthread_t)*nsomadores);
estrutura_geral * estrutura = malloc(sizeof(estrutura_geral));
estrutura->mutex = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(estrutura->mutex,NULL);
estrutura->cond = malloc(sizeof(pthread_cond_t));
pthread_cond_init(estrutura->cond,NULL);
estrutura->produzir = malloc(sizeof(pthread_cond_t));
estrutura->consumir = malloc(sizeof(pthread_cond_t));
estrutura->matriz = malloc(sizeof(int)*n);
buffer = malloc(sizeof(int)*nt);
soma_global = 0;
items_buffer=0;
bloqueio_buffer=nt;
for(i=0;i<n;++i)
estrutura->matriz[i]=i+1;
pthread_mutex_lock(estrutura->mutex);
estrutura->interacoes = nbloco;
if(nbloco==n&&n==nt){
estrutura->interacoes =1;
}
if(nbloco<n/nt || nbloco>n/nt){
estrutura->interacoes =n/nt;
}
estrutura->numero_thread = 0;
for(i=0;i<nsomadores;++i){
pthread_create(&somadoras[i],NULL,funcao_somadora,estrutura);
pthread_cond_wait(estrutura->cond,estrutura->mutex);
}
for(i=0;i<nt;++i){
pthread_create(&calculadoras[i],NULL,funcao_calculadora,estrutura);
++estrutura->numero_thread;
estrutura->inicio = i*estrutura->interacoes;
if(i==(nt-1) && n%nt)
estrutura->interacoes = n-estrutura->interacoes*i;
pthread_cond_wait(estrutura->cond,estrutura->mutex);
}
pthread_mutex_unlock(estrutura->mutex);
for(i=0;i<nt;++i){
pthread_join(calculadoras[i],NULL);}
for(i=0;i<nsomadores;++i){
pthread_join(somadoras[i],NULL);}
printf("A soma do quadrado dos numeros de 1 to %d e %d\n", n,soma_global);
free(estrutura->matriz);
free(buffer);
pthread_cond_destroy(estrutura->cond);
free(estrutura->cond);
pthread_cond_destroy(estrutura->produzir);
free(estrutura->produzir);
pthread_cond_destroy(estrutura->consumir);
free(estrutura->consumir);
pthread_mutex_destroy(estrutura->mutex);
free(estrutura->mutex);
free(estrutura);
free(calculadoras);
free(somadoras);
return 0;
}
this is my first functions it acts as a caculator that produces the date to the buffer that will be consumed from the other thread that is the consumer
void * funcao_calculadora(void * ts){
int i, soma_parcial = 0;
estrutura_geral * const estrutura = ts;
pthread_mutex_lock(estrutura->mutex);
int * const matriz = estrutura->matriz;
int const numero_thread = estrutura->numero_thread;
int const inicio = estrutura->inicio;
int const interacoes = estrutura->interacoes;
pthread_cond_signal(estrutura->cond);
pthread_mutex_unlock(estrutura->mutex);
int const end = interacoes + inicio;
for(i=inicio;i<end;++i){
pthread_mutex_lock(estrutura->mutex);
while(items_buffer == bloqueio_buffer) {
pthread_cond_wait(estrutura->produzir, estrutura->mutex);
}
soma_parcial += matriz[i]*matriz[i];
buffer[items_buffer]=soma_parcial;
items_buffer++;
printf("A thread %d: calculou a soma dos quadrados do bloco de %d to %d, que a soma e %d, estão %d elemnetos no buffer\n",numero_thread,inicio+1,end,soma_parcial, items_buffer);
pthread_cond_signal(estrutura->consumir);
pthread_mutex_unlock(estrutura->mutex);
}
printf("A Thread %u de saida\n",numero_thread);
pthread_exit(NULL);
}
This is my consumer function it consumes the data and cleans the buffer as it consumes the data.
void * funcao_somadora(void * es){
int i;
estrutura_geral * const estrutura = es;
pthread_mutex_lock(estrutura->mutex);
pthread_cond_signal(estrutura->cond);
pthread_mutex_unlock(estrutura->mutex);
for(i=0;i<barreira;++i){
pthread_mutex_lock(estrutura->mutex);
while(items_buffer == 0) {
pthread_cond_wait(estrutura->consumir, estrutura->mutex);
}
soma_global+=buffer[items_buffer];
items_buffer--;
printf("A thread somadora: somou %d, existem %d elemnetos no buffer\n",buffer[items_buffer],items_buffer);
if(items_buffer==0){
sched_yield();
//pthread_cond_signal(estrutura->produzir);
}
pthread_mutex_unlock(estrutura->mutex);
}
printf("A tarefa somadora está de saída\n");
pthread_exit(NULL);
}

Iterating over C array in Go

I am trying to write bindings to a C library. The code is invoked as follows in C:
#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
#include <string.h>
int main(int argc, char *argv[])
{
virConnectPtr conn;
conn = virConnectOpen("qemu:///system");
if (conn == NULL) {
fprintf(stderr, "Failed to open connection to qemu:///system\n");
return 1;
}
int nparams = 0;
virNodeCPUStats* params = malloc(sizeof(virNodeCPUStats) * nparams);
memset(params, 0, sizeof(virNodeCPUStats) * nparams);
int cpuNum = VIR_NODE_CPU_STATS_ALL_CPUS;
if (virNodeGetCPUStats(conn, cpuNum, NULL, &nparams, 0) == 0 &&
nparams != 0) {
if ((params = malloc(sizeof(virNodeCPUStats) * nparams)) == NULL)
goto error;
memset(params, 0, sizeof(virNodeCPUStats) * nparams);
if (virNodeGetCPUStats(conn, cpuNum, params, &nparams, 0))
goto error;
}
int err = virNodeGetCPUStats(conn, cpuNum, params, &nparams, 0);
printf("ret code %d\n", err);
printf("%d nparams\n", nparams);
int i = 0;
for(i = 0; i < nparams; i++){
printf("%s value\n", params[i].field);
printf("%llu value\n", params[i].value);
}
fflush(stdout);
error:
virConnectClose(conn);
return 0;
}
As you see, you first call virNodeGetCPUStats to get the nparams (it returns 4 on linux) then you call with it again with proper size virNodeCPUStats array, and it will fill the values and an output like the following is shown:
ret code 0
4 nparams
kernel value
991550000000 value
user value
4830840000000 value
idle value
199124620000000 value
iowait value
695120000000 value
PASS
Upon reading the code for libvirt-go and ListAllStorageVolumes, I tried the implement the following:
func (c *VirConnection) GetNodeCPUStats(flags C.uint) ([]VirNodeCPUStats, error) {
var nparams C.int
var params *C.virNodeCPUStatsPtr
var cpuNum C.int = -1 // change with cVIR_NODE_CPU_STATS_ALL_CPUS
var stats []VirNodeCPUStats
if C.virNodeGetCPUStats(c.ptr, cpuNum, nil, &nparams, 0) == 0 {
retcode := C.virNodeGetCPUStats(c.ptr, cpuNum, (*C.virNodeCPUStats)(unsafe.Pointer(&params)), &nparams, C.uint(0))
fmt.Println("D> Retcode: ", retcode) --> outputs 0, okay
}
fmt.Println("D> params: ", params)
header := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(params)),
Len: 4,
Cap: 4,
}
slice := *(*[]C.virNodeCPUStatsPtr)(unsafe.Pointer(&header))
for _, ptr := range slice {
stats = append(stats, VirNodeCPUStats{ptr}) //add for first
}
C.free(unsafe.Pointer(params))
return stats, nil
}
However, it gives the following error:
D> params initial: <nil>
D> Successful: virNodeGetCPUStats
D> nparams: 4
D> ret code: 0
D> params: (*libvirt._Ctype_virNodeCPUStatsPtr)(0x6c656e72656b)
D> Header Data: 119182900487531
D> before slice
D> before for
unexpected fault address 0x6c656e72656b
fatal error: fault
[signal 0xb code=0x1 addr=0x6c656e72656b pc=0x4c0c04]
goroutine 87 [running]:
runtime.throw(0x613078, 0x5)
/usr/local/go/src/runtime/panic.go:547 +0x90 fp=0xc820053c80 sp=0xc820053c68
runtime.sigpanic()
/usr/local/go/src/runtime/sigpanic_unix.go:27 +0x2ab fp=0xc820053cd0 sp=0xc820053c80
github.com/rgbkrk/libvirt-go.(*VirConnection).GetNodeCPUStats(0xc820053ef0, 0x0, 0x0, 0x0, 0x0)
/home/tugba/go/src/github.com/rgbkrk/libvirt-go/libvirt.go:879 +0xa84 fp=0xc820053ec0 sp=0xc820053cd0
github.com/rgbkrk/libvirt-go.TestGetCPUStats(0xc8200beea0)
/home/tugba/go/src/github.com/rgbkrk/libvirt-go/libvirt_test.go:833 +0x66 fp=0xc820053f58 sp=0xc820053ec0
testing.tRunner(0xc8200beea0, 0x91acf8)
/usr/local/go/src/testing/testing.go:473 +0x98 fp=0xc820053f90 sp=0xc820053f58
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1998 +0x1 fp=0xc820053f98 sp=0xc820053f90
created by testing.RunTests
/usr/local/go/src/testing/testing.go:582 +0x892
Am I not slicing the C array properly? What is going on? What is unexpected fault and how can it be at an address? Does that mean I am using a memory I shouldn't be?

inserting data in sqlite3 through C

I have a problem about inserting data into a sqlite3 database. The database permissions were set to 777 (just for the development environs), and the same goes with the directory.
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sqlite3.h>
#include <string.h>
#define MAXLENGTH 255
int random_add(int base, int mod, int interval)
{
int addend;
struct timeval tv;
gettimeofday(&tv, NULL);
srand((unsigned)tv.tv_usec);
addend = base + rand() % mod + (interval);
return addend;
}
int random_wlvl(int own_lvl)
{
int wlvl = random_add(own_lvl, 7, -3);
return wlvl;
}
int random_wstat(int pstat, int wlvl, int mod, int interval)
{
int wstat = random_add(pstat,11,-5);
while(--wlvl) {
wstat = random_add(wstat,mod,interval);
}
return wstat;
}
int main(void)
{
int own_id = 2;
int error = 0;
sqlite3 *conn;
sqlite3_stmt *res;
error = sqlite3_open("whorl.sl3", &conn);
if (error) {
puts("Cannot open database");
exit(0);
}
char temp[MAXLENGTH];
int i,battle_id;
// Start of Wild Nemesis Selection
int wlvl,whp,watk,wdef; //wild nemesis stats
int wpid = random_add(0,13,1);
int own_lvl,nem_id, own_hp;
sprintf(temp, "select nem_hp,nem_atk,nem_def from nemesis where nem_id = %d union all select own_lvl,nem_id, own_hp from owned where own_id = %d;",wpid,own_id);
error = sqlite3_prepare_v2(conn, temp, MAXLENGTH, &res, NULL);
if (error != SQLITE_OK) {
puts("Did not receive data from nemesis,owned");
exit(0);
}
i = 0;
while (sqlite3_step(res) == SQLITE_ROW) {
if (i == 0){
whp = sqlite3_column_int(res,0);
watk = sqlite3_column_int(res,1);
wdef = sqlite3_column_int(res,2);
} else {
own_lvl = sqlite3_column_int(res,0);
nem_id = sqlite3_column_int(res,1);
own_hp = sqlite3_column_int(res,2);
}
i++;
}
sqlite3_finalize(res);
//randomize wstats
wlvl = random_wlvl(own_lvl);
whp = random_wstat(whp,wlvl,5,6);
watk = random_wstat(watk,wlvl,5,1);
wdef = random_wstat(wdef,wlvl,5,1);
//create battle
sprintf(temp,"insert into battles(own_id,nem_id,own_hp,wpid,wlvl,whp,watk,wdef,wmaxhp) values(%d,%d,%d,%d,%d,%d,%d,%d,%d);",own_id,nem_id,own_hp,wpid,wlvl,whp,watk,wdef,whp);
error = sqlite3_exec(conn,temp,0,0,0);
if (error) {
puts("Cannot insert into battles");
exit(0);
}
sprintf(temp,"select battle_id from battles where own_id = %d;",own_id);
error = sqlite3_prepare_v2(conn,temp,MAXLENGTH,&res,NULL);
if (error != SQLITE_OK) {
puts("Cannot get battle_id");
}
while(sqlite3_step(res) == SQLITE_ROW) {
battle_id = sqlite3_column_int(res,0);
}
sqlite3_finalize(res);
sqlite3_close(conn);
printf("battle_id = %d\n", battle_id);
return 0;
}
Compiling, and then running yields the following:
$ ./a.out
Cannot insert into battles
Here is my schema for the battles
sqlite> .schema battles
CREATE TABLE battles(battle_id integer primary key autoincrement, own_id integer, pok_id integer, wpid integer, wlvl integer, whp integer, watk integer, wdef integer, wmaxhp integer);
What's wrong? Why can't I insert some data?

Resources